Reporting about all the different OS Deployment Versions with ConfigMgr 2012

One of the biggest challenges with OS Deployment is keeping track of all the different deployments and everything that changed between the deployments. This post will focus on the first part, keeping track of all the different deployments. I will do that by showing a way to write information to the registry, creating a hardware inventory for those registry keys and building a report on the inventory data. For the second part, keeping track of all the changes, take a look at this great post of Maik Koster.

Create registry keys

Reg_DepVerThe first thing is to create a script that will write information about the deployment to the registry. As a deployment is much more then just the image, we need information about the task sequence. There are multiple ways to put a version number somewhere in the task sequence. I choose to write a version number in the task sequence name. Besides that I also write some extra information to the registry about the different Id’s and how it was deployed (see picture). To do this I use a very basic script like this (change PETERTEST to something different, like a company name):

Dim strAdvertisementID, strOrganisationName, strTaskSequenceID, strPackageName, strMediaType, strInstallDate, strKeyPath
Dim objEnv, objReg

Set objEnv = CreateObject(“Microsoft.SMS.TSEnvironment”)
Set objReg = GetObject(“winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv”)

Const HKEY_LOCAL_MACHINE = &H80000002

‘Set variables
strAdvertisementID = objEnv(“_SMSTSAdvertID”)
strOrganisationName = objEnv(“_SMSTSOrgName”)
strTaskSequenceID = objEnv(“_SMSTSPackageID”)
strPackageName = objEnv(“_SMSTSPackageName”)
strMediaType = objEnv(“_SMSTSMediaType”)

‘Tattoo information in registry
strKeyPath = “SOFTWARE\PETERTEST”
objReg.CreateKey HKEY_LOCAL_MACHINE,strKeyPath

strValueName = “AdvertisementID”
objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strAdvertisementID

strValueName =”InstallDate”
strInstallDate = FormatDateTime(date,2) & ” ” & FormatDateTime(time,3)
objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strInstallDate

strValueName = “MediaType”
objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strMediaType

strValueName = “OrganisationName”
objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strOrganisationName

strValueName = “PackageName”
objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strPackageName

strValueName = “TaskSequenceID”
objReg.SetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strTaskSequenceID

‘Clean up
Set objEnv = Nothing
Set objReg = Nothing

TSEd_DepVerNow to run this script, save it as a vbs file and add it to a package. In the  task sequence (see picture) add a Run Command Line –step, select Package and Browse to the package with the new script. In the Command line add cscript.exe <ScriptName> and select Disable 64-bit file system redirection. This last action makes sure that the registry information will be written to the same key on all systems, so there is no need for multiple inventory classes.

Extend Hardware Inventory

RegKeyToMofThe second thing is to create a hardware inventory for the newly created registry keys. There are two ways to do this. The first one is to create our own extensions and the second one is to use the tool RegKeyToMof. I choose to use the second way, as that tool makes my life a whole lot easier. On a computer, which has run the task sequence, open the tool RegKeyToMOFv31 and browse in the top screen to the new registry key. In the bottom screen it will now show the necessary extensions for the different MOF files. Also fill in a good Class Name (I use DeploymentVersion), as this will also be part of the table and view names in the database.

Now go to <InstallDir>\inboxes\clifiles.src\hinv, open the configuration.mof, go all the way to the bottom of this file and add the content of the configuration.mof –tab between the lines Added extensions start and Added extensions end. Assuming this is the first extensions, it will make it look similar to this (remember that PETERTEST might be different, when it’s changed in the initial script):

//========================
// Added extensions start
//========================

#pragma namespace (“\\\\.\\root\\cimv2”)
#pragma deleteclass(“DeploymentVersion”, NOFAIL)
[DYNPROPS]
Class DeploymentVersion
{
[key] string KeyName;
String AdvertisementID;
String InstallDate;
String MediaType;
String OrganisationName;
String PackageName;
String TaskSequenceID;
};

[DYNPROPS]
Instance of DeploymentVersion
{
KeyName=”Deployment_Version”;
[PropertyContext(“Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\PETERTEST|AdvertisementID”),Dynamic,Provider(“RegPropProv”)] AdvertisementID;
[PropertyContext(“Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\PETERTEST|InstallDate”),Dynamic,Provider(“RegPropProv”)] InstallDate;
[PropertyContext(“Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\PETERTEST|MediaType”),Dynamic,Provider(“RegPropProv”)] MediaType;
[PropertyContext(“Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\PETERTEST|OrganisationName”),Dynamic,Provider(“RegPropProv”)] OrganisationName;
[PropertyContext(“Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\PETERTEST|PackageName”),Dynamic,Provider(“RegPropProv”)] PackageName;
[PropertyContext(“Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\PETERTEST|TaskSequenceID”),Dynamic,Provider(“RegPropProv”)] TaskSequenceID;
};

//========================
// Added extensions end
//========================

After this go to the to import in Admin/AgentSettings/HardwareInventory/SetClasses/Import –tab and add the content to a new (temporary) MOF file. This will create a MOF file with the following content:

#pragma namespace (“\\\\.\\root\\cimv2\\SMS”)
#pragma deleteclass(“DeploymentVersion”, NOFAIL)
[SMS_Report(TRUE),SMS_Group_Name(“DeploymentVersion”),SMS_Class_ID(“DeploymentVersion”)]
Class DeploymentVersion: SMS_Class_Template
{
[SMS_Report(TRUE),key] string KeyName;
[SMS_Report(TRUE)] String AdvertisementID;
[SMS_Report(TRUE)] String InstallDate;
[SMS_Report(TRUE)] String MediaType;
[SMS_Report(TRUE)] String OrganisationName;
[SMS_Report(TRUE)] String PackageName;
[SMS_Report(TRUE)] String TaskSequenceID;
};

HarInvClaNow open the Configuration Manager Console and navigate to Administration > Client Settings. Open (for example) the Default Client Settings, go to Hardware Inventory and click Set Classes. In the Hardware Inventory Classes, click Import and Open the new (temporary) MOF file. This will show the new class for the inventory.

Create report

The third, and last, thing to do is to create a report based on the new registry information. This is probably a lot easier then you might think, because adding a new class to the hardware inventory also creates new tables and views in the database. As I used DeploymentVersion, as the class name for the extension of the hardware inventory, the view in the database with the information is named v_GS_DeploymentVersion. So to get the new information in a report, including computer name, we need the following query:

SELECT     v_R_System.Name0, v_GS_DeploymentVersion0.AdvertisementID0, v_GS_DeploymentVersion0.InstallDate0, v_GS_DeploymentVersion0.MediaType0,
                      v_GS_DeploymentVersion0.OrganisationName0, v_GS_DeploymentVersion0.PackageName0, v_GS_DeploymentVersion0.TaskSequenceID0
FROM         v_GS_DeploymentVersion0 INNER JOIN
                      v_R_System ON v_GS_DeploymentVersion0.ResourceID = v_R_System.ResourceID
ORDER BY v_R_System.Name0

Now to put all the pieces together, open SQL Server Report Builder 3.0 and create a new report. Add a Data Source to the ConfigMgr database and create a DataSet with the previously mentioned query. The last things to do is add a table to report, add the necessary fields and save the report between the other ConfigMgr Reports. Open the Configuration Manager Console, navigate to Monitoring > Overview > Reporting > Reports and that’s where the new report will show up.

Result

Wondering what the end result looks like? Well, here is a basic example of what it will look like:

Rep_DepVer

19 thoughts on “Reporting about all the different OS Deployment Versions with ConfigMgr 2012

  1. I’ve tried the steps above but I’m recieving “The MOF file you tried to import could not be compiled. Ensure that the MOF file contains valid data. You can use the command line mofcomp utility to test the data.” when importing the MOF file created from the second tab. I ran a MOFCOMP against the mof file and recieved an error:

    An error occurred while creating object 2 defined on lines 8 – 13:
    0X80041002 Class, instance, or property ‘SMS_Class_Template’ was not found.
    Compiler returned error 0x80041002

    Was this all done on the server? Was there any other steps you needed that are associated to the SMS_Class_Template?

  2. There is a step missing somewhere here, I am getting the same result
    “The MOF file you tried to import could not be compiled. Ensure that the MOF file contains valid data”
    This part doesnt make sense, can you please elaborate?- After this go to the to import in Admin/AgentSettings/HardwareInventory/SetClasses/Import –tab and add the content to a new (temporary) MOF file. This will create a MOF file with the following content:

  3. Hi Ryan,
    In RegKeyToMOF under ConfigMgr12 there are two tabs, one is configuration.mof and two is to import in Admin/AgentSettings/HardwareInventory/SetClasses/Import. So going to the second tab will give you the information needed for that.
    Peter

  4. Peter, love the idea behind this and I’m trying to implement it, however when I run the script in the TS i get a Failed with he error code (0x00000001)

    I’d appreciate any thoughts you have?

  5. Hi Peter, the smstslog lists it as “incorrect function”

    I have created a package, with the vbs script copied from the above and ran it at the end of the TS with the same setup as you have.

  6. Hi Steve,
    As the script is pretty straight forward, I can only imagine that something went wrong with copying and pasting the code. I just noticed it myself too that a copy-paste action from my blog to notepad just screws up the quotes, both single (‘) and double (“). Also try to test run it from a task sequence environment (either by pausing a task sequence, or when a task sequence failed) to gets some more feedback.
    Peter

  7. Hi Peter, I’ve tried it again and ran it after pausing the TS – it gives me line 4, char 31 error invalid character.

    Would it be possible for you to email me the script as it should be?

    Appreciate your help with this.

    Steve

  8. I had some problems with this procedure as I was trying to edit custom client settings rather than the default client settings, once I did that everything worked fine. Thank you for this write up Peter, very useful info.

  9. Hi Peter, how are you doing today?

    I would like to thank you for your script and for the step-by-step for the report.

    I got the script working fine, I get all the keys, etc.

    For the MOF file, all good as well, could add the configuration.MOF on my SCCM server normally. I also imported the custom.MOF file with the results from the RegtoMOT tool. all good.

    My Only issue is in the SQL Server (Report creation part). I am not a SQL person, and I cant figure out how to do the SQL part in order to create the Tables, etc.

    Would you be able to detail a little bit on the very last part when it says: (Add a Data Source to the ConfigMgr database and create a DataSet with the previously mentioned query. The last things to do is add a table to report, add the necessary fields and save the report between the other ConfigMgr Reports. ).

    Thank you for your help.

    Eden Oliveira

  10. Hi Peter, how are you? thank you for your reply to my question. I have a question for you. When I run the query against my SQL DB, I got somehow all computers on my SCCM DB, instead of only the ones I have deployed so far and I also get all columms with NULL values.

    Do you know what I am doing wrong?

    Thanks a lot!

    SELECT v_R_System.Name0, v_GS_OSDInfo0.AdvertisementID0, v_GS_OSDInfo0.InstallDate0, v_GS_OSDInfo0.MediaType0,
    v_GS_OSDInfo0.OrganisationName0, v_GS_OSDInfo0.PackageName0, v_GS_OSDInfo0.TaskSequenceID0
    FROM v_GS_OSDInfo0 INNER JOIN
    v_R_System ON v_GS_OSDInfo0.ResourceID = v_R_System.ResourceID
    ORDER BY v_R_System.Name0

  11. Hi Peter,
    Great article, helped out a lot. I’m a bit fuzzy on the last steps though, was wondering if you could email me the .rdl file to import for the report.

    I’ve created the datasets and just need to add the table, but not sure what fields to add.

    Thanks,
    Luke

  12. Hi Luke,

    I’m sorry, but I don’t have that report in my current lab. However, it shouldn’t be to difficult. It should be pretty straight forward with the notes after the SQL query.

    If not, please let me know which part is difficult to understand.

    Peter

Leave a Comment