ENow Blog | Exchange Center

How to Build a SCCM OSD Progress Report to Wow Your Boss - Part 1

Written by ENow Software | Mar 8, 2021 9:03:00 PM

Microsoft SCCM (and MDT) are great tools that provide a robust system to lay down OS images onto many clients. Once setup, SCCM admins and technicians can easily image computers all day every day without thinking about how much time and money they’re saving the company. Rather than just telling your boss you’re making progress on something like the Windows XP replacement project you’ve got going on why not give her/him real, hard numbers of how many devices you’ve been knocking out over the past 6 months?

To do this we’re going to need to build a SCCM report. We need a report that will show us, historically, how many PCs we’ve imaged over a set amount of time. I’m also going to go out on a limb and say we want this report to update automatically and to not require any kind of intervention. Do I have your interest? I hope so!

Before we get started building this boss-loving and beautiful report we should first outline how it  will work. Retrieving historical data from the database server in a report requires a few different steps which I’ll be discussing in this article series. In part 1 of the series I’ll show you where the information is stored on the client that you’ll need to gather to determine if the client was imaged with SCCM or MDT. Once I know what I’m looking for I’ll then go over how to get this information into the SCCM database through creating a custom hardware inventory class.

In part 2 of the series, I’ll go over how to verify that the hardware inventory class was setup correctly by going over the pertinent logs and show you what query I created inside the SCCM console to quickly ensure the clients are sending the right information to the database.

Finally, in part 3, I’ll go into the process and details of creating the report itself. I’ll provide the SQL query you’ll need in order to build the report and briefly go over creating the SSRS report which will ultimately lead to a happy boss!

Find the Existing Data on the Client

There are a number of different ways to report on your imaging process. The key is to have some kind of static placeholder either on the client or on the site server to retrieve historical data like every time a client OS was deployed. It’s my goal with this report to figure out a way to get the information I need (whether or not the OS was applied with SCCM) without any kind of intervention. I want to simply gather any information that, by default, is added either to each client or in the site server database itself.

I say this because prior to building this report I came across a few different ways others were solving this problem. I found some people creating a step in each of their task sequences to create a registry value on each client. I also found some references to others ensuring they used the same task sequence for all their deployments. These steps would certainly store the information we need to do this however, there is a major flaw; human intervention— Humans forget things and are bound to screw up.

I always prefer the solution that requires little or no ongoing intervention, a process that is  simple as possible and just works. This is why I chose to use a native MDT function called MDT Tattoo. When a system is built with MDT integration, a script called ZTITatoo.wsf is executed which writes some very useful information about the deployment into the registry. If you need the specifics click through on the link above but in general, every time a MDT deployment is done a few registry values are written to the client which acts as a permanent tattoo as to how that image was applied.

In addition to the registry values stored I will also be using WMI; more specifically, the Microsoft_BDD_Info WMI class. By using data inside the registry as well as a WMI class I’ll be able to accurately define which clients were imaged via SCCM/MDT and which ones were installed via a CD, for example.

Extend SCCM’s default hardware inventory classes

Now that I know that the information I’m looking for is stored on each client I can’t just query all the clients with Powershell, and be done. We’re looking for a historical, always upto-date report here. For this reason, we need to get this data inside the SCCM database. To do this, I need to add a custom hardware inventory class to instruct each SCCM client to gather both a WMI class and a registry value.

I won’t be going into detail on how to add a custom inventory class however, if you feel you need more information, feel free to click through the link above. To save you some time I’ve included a prebuilt MOF file below. You’ll need to import this into the Default Client Settings agent settings. Once you do this, you will then see a new class called OSD History. This will be the inventory class that will go into the SCCM database in which the query you write later will depend on. This MOF file depends on the Microsoft_BDD_Info WMI class which gets created by the MDT process.
Go ahead and copy this out into a text file, save it with a .MOF extension and import it into Default Client Settings.

#pragma namespace ("\\\\.\\root\\CIMv2")
[ SMS_Report (TRUE),
SMS_Group_Name ("OSD History"),
SMS_Class_ID ("MICROSOFT|MICROSOFT_BDD_INFO|1.0"),
Namespace ("\\\\\\\\.\\\\root\\\\cimv2") ]
class Microsoft_BDD_Info : SMS_Class_Template
{
[ SMS_Report (TRUE), key ]
String     InstanceKey;
[ SMS_Report (FALSE) ]
String     BuildID;
[ SMS_Report (FALSE) ]
String     BuildName;
[ SMS_Report (FALSE) ]
String     BuildVersion;
[ SMS_Report (TRUE) ]
String     DeploymentMethod;
[ SMS_Report (TRUE) ]
String     DeploymentTimeStamp;
[ SMS_Report (TRUE) ]
String     DeploymentType;
[ SMS_Report (FALSE) ]
String     OSDAdvertisementID;
[ SMS_Report (FALSE) ]
String     OSDPackageID;
[ SMS_Report (FALSE) ]
String     OSDProgramName;
[ SMS_Report (TRUE) ]
String     TaskSequenceID;
[ SMS_Report (TRUE) ]
String     TaskSequenceName;
[ SMS_Report (TRUE) ]
String     TaskSequenceVersion;
};

By now you should have an OSD History inventory class which contains attribute about imaging done via MDT. In order to find non-MDT images I also have to gather a registry value called CM_DSLID. This value is located in theHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT registry key. It contains the ID of the deployment that applied the image when not using MDT.

Extending the hardware inventory to gather a registry value is a little more difficult but not impossible. First, I have to make a change to the configuration.of file on the SCCM site server. Again, to save you some time I’ve included what you need to add to the end of your configuration.mof file.

To generate this text, I used the very handy regtomof utility by Mark Cochrane. I highly recommend this utility when extending your hardware inventory. It makes creating MOF files in reference to registry values extremely easy. Go ahead and paste this text to the end of your configuration.mof file.

#pragma namespace ("\\\\.\\root\\cimv2")
#pragma deleteclass("OSD_History_2", NOFAIL)
[DYNPROPS]
Class OSD_History_2
{
[key] string KeyName;
String CM_DSLID;
};
[DYNPROPS]
Instance of OSD_History_2
{
keyname="OSD_Deployment_Id";
[PropertyContext("Local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion|CM_DSLID"),Dynamic,Provider("RegPropProv")] CM_DSLID;

Once you’ve changed your configuration.mof file you now have to, again, create a MOF file and import it into Default Client Settings. Here’s that MOF file contents for you. This will create a OSD_History2 inventory class. (Forgive the name. I’m not too original.)

#pragma namespace ("\\\\.\\root\\cimv2\\SMS")
#pragma deleteclass("OSD_History_2", NOFAIL)
[SMS_Report(TRUE),SMS_Group_Name("OSD_History_2"),SMS_Class_ID("Custom|OSD_History_2|1.0")]
Class OSD_History_2: SMS_Class_Template
{
[SMS_Report(TRUE),key] string KeyName;
[SMS_Report(TRUE)] String CM_DSLID;
};

By the time you’ve gotten these steps done you will see something like this.

You’ve now extended SCCM’s hardware inventory to instruct the client’s to begin gathering the information we need as part of their hardware inventory cycle. Once each client requests a new machine policy and subsequently runs its next hardware inventory cycle it should successfully report the information up to the site database. But how do we know for sure? This is the topic of Part 2 of the article series!