In regards to drivers and BIOS updates on workstations in your environment, a lot of organizations have held the mindset for many years that ‘If it ain’t broke, don’t fix it!‘. We did too up until we had a Windows Desktop RaaS with Microsoft in 2014.
Premier Services site: https://services.premier.microsoft.com/assess?
What we found is that by not managing our driver and BIOS versions, we had no baseline, and there for a very difficult time troubleshooting hardware and performance related issues. Now we inventory our driver information in SCCM, and can report on how we are doing with versions out in our environment. This information is not available out of the box, so it takes a little setup.
Inventoring the Win32_PnpSignedDriver WMI class
- This class cannot be inventoried directly, so a custom WMI class must be created and populated
- This has been tried before, and not many had luck
- http://www.systemcentercentral.com/forums-archive/topic/win32_pnpsigneddriver-inventory/
- https://blogs.technet.microsoft.com/configmgr_geek_speak/2013/11/10/inventorying-and-reporting-network-adapter-driver-details-and-how-to-report-only-the-wireless-type-with-bonus-mini-primer-on-sql-report-builder-in-configuration-manager-2012/
- http://www.myitforum.com/forums/SMS-MOF-file-for-Win32_PnPSignedDriver-m178956.aspx
- https://social.technet.microsoft.com/Forums/systemcenter/en-US/20e7e3f7-31c0-48f5-9d99-5d2b215bb218/win32pnpsigneddriver-diles-to-add-to-smsdefmof?forum=configmgrgeneral
- Special thanks to EASULIN and Sherry Kissinger for providing the bulk of the process and inventory scripts
Like all scripts, they should be written in PowerShell, so I created one for a SCCM Script Compliance Item in PowerShell.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
## Define new class name and date $NewClassName = 'Win32_PnpSignedDriver_Custom' $Date = get-date ## Remove class if exists Remove-WmiObject $NewClassName -ErrorAction SilentlyContinue # Create new WMI class $newClass = New-Object System.Management.ManagementClass ("root\cimv2", [String]::Empty, $null) $newClass["__CLASS"] = $NewClassName ## Create properties you want inventoried $newClass.Qualifiers.Add("Static", $true) $newClass.Properties.Add("DeviceClass", [System.Management.CimType]::String, $false) $newClass.Properties.Add("DeviceName", [System.Management.CimType]::String, $false) $newClass.Properties.Add("DriverDate", [System.Management.CimType]::DateTime, $false) $newClass.Properties.Add("DriverProviderName", [System.Management.CimType]::String, $false) $newClass.Properties.Add("DriverVersion", [System.Management.CimType]::String, $false) $newClass.Properties.Add("HardwareID", [System.Management.CimType]::String, $false) $newClass.Properties.Add("DeviceID", [System.Management.CimType]::String, $false) $newClass.Properties.Add("ScriptLastRan", [System.Management.CimType]::String, $false) $newClass.Properties["DeviceName"].Qualifiers.Add("Key", $true) $newClass.Properties["DeviceID"].Qualifiers.Add("Key", $true) $newClass.Put() | Out-Null ## Gather current driver information Get-WmiObject win32_pnpsigneddriver -Property DeviceClass, DeviceName,DriverDate,DriverProviderName,DriverVersion,HardwareID,DeviceID | where{$_.DeviceClass -ne 'VOLUMESNAPSHOT' -and $_.DeviceClass -ne 'LEGACYDRIVER' -and $_.DriverProviderName -ne 'Microsoft' -and $_.DriverVersion -notlike "2:5*"} | ForEach-Object { ## Set driver information in new class Set-WmiInstance -Namespace root\cimv2 -class $NewClassName -argument @{ DeviceClass = $_.DeviceClass; DeviceName = $_.DeviceName; DriverDate = $_.DriverDate; DriverProviderName = $_.DriverProviderName; DriverVersion = $_.DriverVersion; HardwareID = $_.HardwareID; DeviceID = $_.DeviceID; ScriptLastRan = $Date } | Out-Null } Write-Output "Complete" |
A few notes:
- A new WMI class Win32_PnpSignedDriver_Custom is created. Edit $NewClassName if you would like to change it.
- The custom class is deleted and recreated on each run
- The following Properties are inventoried: DeviceClass, DeviceName, DriverDate, DriverProviderName, DriverVersion, HardwareID, DeviceID
- The timestamp is inventoried
- Feel free to edit the filter for your own organizations needs
- $_.DeviceClass -ne ‘VOLUMESNAPSHOT’ -and $_.DeviceClass -ne ‘LEGACYDRIVER’ -and $_.DriverProviderName -ne ‘Microsoft’ -and $_.DriverVersion -notlike “2:5*”
Download the Configuration Item CAB here: Script – Windows – PNP Signed Drivers
Once the script has been deployed and ran on a few machines, just connect to WMI and you can add the new Win32_PnpSignedDriver_Custom class to your SCCM hardware inventory.
Reporting on driver versions
Once you have the data in your inventory, you just need to report on it.
The SQL view v_gs_pnp_signed_driver_custom gets created from your hardware inventory and contains all the raw data. Here are a few sample SQL queries:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
-- Raw data select * from v_gs_pnp_signed_driver_custom -- All network drivers list select DeviceClass0, DeviceName0, DriverDate0, DriverProviderName0, DriverVersion0 from v_gs_pnp_signed_driver_custom where DeviceClass0 = 'NET' -- All LAN network drivers count select DeviceName0 [Name], DriverVersion0 [Version], count(*) [Total] from v_gs_pnp_signed_driver_custom where DeviceClass0 = 'NET' and DriverProviderName0 in ( 'Broadcom', 'Intel', 'Marvell', 'Microsoft Corporation', 'Realtek', 'Realtek Semiconductor Corp.') and DeviceName0 not in ( 'ThinkPad OneLink Pro Dock Giga Ethernet', 'Thinkpad USB 3.0 Ethernet Adapter', 'Microsoft Windows Mobile Remote Adapter', 'Remote NDIS based Internet Sharing Device') and ( DeviceName0 not like '%Wireless%' and DeviceName0 not like '%WLAN%' and DeviceName0 not like '%Centrino%' and DeviceName0 not like '%WiFi%') group by DeviceName0, DriverProviderName0, DriverVersion0 order by DriverProviderName0, DeviceName0, DriverVersion0 -- All WLAN network drivers count select DeviceName0 [Name], DriverVersion0 [Version], count(*) [Total] from v_gs_pnp_signed_driver_custom where DeviceClass0 = 'NET' and DriverProviderName0 in ( 'Broadcom', 'Intel', 'Marvell', 'Microsoft Corporation', 'Realtek', 'Realtek Semiconductor Corp.') and DeviceName0 not in ( 'ThinkPad OneLink Pro Dock Giga Ethernet', 'Thinkpad USB 3.0 Ethernet Adapter', 'Microsoft Windows Mobile Remote Adapter', 'Remote NDIS based Internet Sharing Device') and ( DeviceName0 like '%Wireless%' or DeviceName0 like '%WLAN%' or DeviceName0 like '%Centrino%' or DeviceName0 like '%WiFi%') group by DeviceName0, DriverProviderName0, DriverVersion0 order by DriverProviderName0, DeviceName0, DriverVersion0 |
Here is a look at some of the raw data:
It was asked by a few members of the community what impact this may have on your database, and how large the table may be. My data is below, but you will need to judge for yourself if this would be an impact to your environment.
There are 77,767 unique resource IDs (total clients reporting) in this table in our environment.
TableName | SchemaName | RowCounts | TotalSpaceKB | UsedSpaceKB | UnusedSpaceKB |
PNP_SIGNED_DRIVER_CUSTOM_DATA | dbo | 0 | 32 | 32 | 0 |
PNP_SIGNED_DRIVER_CUSTOM_DATA | dbo | 639759 | 514512 | 512840 | 1672 |
PNP_SIGNED_DRIVER_CUSTOM_DATA | dbo | 983014 | 767456 | 764480 | 2976 |
PNP_SIGNED_DRIVER_CUSTOM_DATA_DD | SCCM_Ext | 911122 | 40752 | 40656 | 96 |
We use the two LAN and WLAN queries above to create a network driver dashboard to report on how standardized we are. We highlight the current standard versions to quickly see any drift.
The .RDL is tailored for our environment, primarily Intel NICs with a few Broadcom and Realtek, so you may need to customize it for your models. The highlights also are “point in time” choices, and will also need to be modified for your needs.
Network – Workstation Dashboard
Enjoy!
I couldn’t resist commenting. Very well written!
This is terrific, Ive been working figuring out how to create driver baselines for weeks with no success. I’m having trouble getting the inventory class into SCCM 2012. Can you provide some more details? Thanks
Sure! Here is the TechNet docs: https://technet.microsoft.com/en-us/library/gg712290.aspx and here is a friendlier walkthrough: http://powershelldistrict.com/how-to-extend-hardware-inventory-in-configuration-manager/.
Let me know if the issue is that the WMI class isn’t there, that would be a different story.
[…] default SCCM doesn’t collect drive info. Potent Engineer have a great post about adding driver info to […]
Looks clean. What if any impact on HINV if managing 10k endpoints?
The only impact is the size of your DB. We inventory over 100 things with HINV, and it runs in about 60 seconds on all of our machines.
Great post Daniel – Many thanks. A couple of queries;
Do I need to run the script on all client systems? I have only ran it on one by managed to add the custom class to our inventory.
How long would you expect for it to take for the database to be populated with results? I presume it is dependant on the Hardware Inventory schedule within the default client settings………
The scope of clients you want the inventory information on would be who you would target, for both your inventory script as well as client settings to inventory the class. You could target as few or as many as you want. We target all physical workstations for our needs.
Your hardware inventory cycle schedule does play a part, so it should never take longer than that cycle, plus a little processing time policy to the MP, MP to drop the inventory file, and for the inbox to update and SQL to be injected. We run our HINV daily across all clients so we never expect data to be more than a day or so old.
Nice script, WMI class and reports 🙂 Thanks!
Does the script need to run on a schedule to collect updated information about drivers beeing updated?
Or is the WMI class dynamic ?
just looking at the “scriptLastRan” value…
//John
Thanks! Yes, the compliance item will need to be re-ran on a schedule to populate new information. We run ours weekly or monthly in some cases.
Your way of explaining the whoe thing in this post is actually nice, all be
capable of without dificulty know it, Thanks a lot.
Can you give more details on the CI creation? This part has me hung up. I am able to create the class if I run the script manually, but for some reason the CI is not creating the class for the clients. I am able to see that the CI is running, and I can run the CI from the client ad-hoc, but no dice on the WMI class creation. Thoughts?
Sorry for the delay! Are you running the script as a monitor, not remediate? Double check your x86/x64 settings as well. We only have x64 clients so we do not check the box to run as x86.
I just updated the post with my exact CI export. Give it a try!
I’m having the same trouble as Curtis. Could you send me a few screenshots of your CI settings?
I updated the post with my CI CAB. Give it a try!
It turns out it was an issue with the certificate we used to sign the script. So the CI and baseline are now working when ran manually* but I’m having some trouble with the evaluation schedule. I set a “simple schedule” to run the compliance evaluation every 30 minutes on my test collection but it doesn’t seem to be running at all.
*Open CM Configurations tab, manually run it by clicking “Evaluate”. The Last Evaluation column updates with the current date and time, the compliance column shows compliant. Open a PowerShell window and run “get-wmiobject win32_pnpsigneddriver_custom | select DeviceName, DriverVersion, ScriptLastRan” the driver version column is updated if a driver was changed and the ScriptLastRan column shows the same info as the Last Evaluation column in the CM Configurations tab.
Although the technical limit for it to re-evaluate is 15 minutes, 30 minutes might still be too often. There is also the 2 hour randomization that may impact it running so soon. From experience we usually never set anything to run more than every 2 hours. Most of our baselines deploy once a day.
Torsten has a great explanation here: https://social.technet.microsoft.com/Forums/en-US/9fa2fe83-90fc-4e73-ab2f-6d350ec29016/frequent-configuration-baseline-evaluation?forum=configmgrgeneral.
Official doc: https://technet.microsoft.com/en-us/library/bb680847.aspx
Hi Daniel, the link gives a 500 – Internal server error…
Sorry about that, it is fixed!
This is the greatest thing since sliced bread! I love it. Can you share the RDL files of the reports? I would love to use them.
Done! They will need to be customized for your needs, but the framework is there!
Thx a bunch. The green highlight in the dashboard, is it meant to highlight the newest driver? Or what does it do?
For us it represents our current stable driver version. We manually set it, but it could definitely be done dynamically just looking for the max version if you wanted.
Hi there, i’m not seeing the view in the SCCM DB any clue why it would still be missing after running for a week and over 1000 clients checking in?
Make sure you extend hardware inventory to start collecting it.
https://docs.microsoft.com/en-us/sccm/core/clients/manage/inventory/extend-hardware-inventory
I’m having the same issue. It runs on all of the devices as I expect with the configuration item. I connected my hardware inventory to a device and imported the class into the hardware inventory. All boxes are checked. If I loop thorugh my devices they all have this locally. Unfortunately, when I browse to SMS/Site_ with WMI Explorer I do not see the custom table, only the regular Microsoft PNP table. I went ahead and followed your instructions again and removed and re-added it to hardware inventory just in case. I also made sure to cross referenced the above link.
I’ve checked the inventoryagent.log, no errors but this is what is has to say about the table:
Any ideas? TL;DR My hardware inventory says it’s being collected but it doesn’t appear to be in the hardware inventroy WMI table.
Sounds like the client piece is working correctly. If the clients have the WMI entries locally the CI is working, SCCM just has to tell the client to collect it.
When you added the class to Default Client Settings, did you enable it? If you have a custom hardware inventory client setting, make sure to enable it there, or whatever client setting is deployed to your clients.
if that still doesn’t work, remove the class, monitor dataldr.log on your site server, then re-enable the class. There may be an error or other info in the log that may help identify the issue.
By “enable” it do you mean check the box for the class?
Also, I guess I forgot to past the log entry I alluded to above.
Yes sir, just checking it in your client settings.
or…the html formatting was removing it. Hopefully this one works.
![LOG[Collection: Namespace = root\cimv2; Query = SELECT __CLASS, __PATH, __RELPATH, DeviceID, DeviceName, DeviceClass, DriverDate, DriverProviderName, DriverVersion, HardwareID, ScriptLastRan FROM Win32_PnpSignedDriver_Custom; Timeout = 600 secs.]LOG]!><time="11:21:47.727+420" date="09-10-2018" component="InventoryAgent" context="" type="1" thread="10496" file="collectiontask.cpp:478"
Ok I did what you suggested. I got no string of errors after doing so. Searching the log, I found this. Googling this is returning BadMIF threads but I’m not having a problem with a single or handful of devices generally. I did look at the device this error was referencing and it didn’t have the table. Overall though, I expect that to be a small subset of devices out of thousands that do have it.
ERROR – attempt to update non-existent row (sp = pPNP_SIGNED_DRIVER_CUSTOM_DATA). Invalid command: exec dbo.pWorkstationStatus_DATA 1,16787971,’09/11/2018 14:22:41′,1,’9/11/2018 14:21:44′,N’8589934848′,1033,-420 SMS_INVENTORY_DATA_LOADER 9/11/2018 2:22:41 PM 12796 (0x31FC)
I had originally misdiagnosed the issue. There is nothing wrong with reporting to the hardware inventory, but I can only seem to get at it using the v_gs_pnp_signed_driver_custom sql method you have outlined above.
However, I need to build WQL queries for dynamic collections that dig into the SMS\Site_STC namespace. For example, cimv2\WIN32_PNPSIGNEDDRIVER is also stored at sms\site_stc\ as SMS_G_SYSTEM_PNP_DEVICE_DRIVER. From my research this is controlled by SMS_InventoryReport and SMS_InventoryReportClass.
I’ve found some useful code for achieving this at https://scadminsblog.wordpress.com/category/sccm-hardware-inventory/ that will hopefully solve this problem. I’ll post my solution when I get it working.
Sounds good. FYI, you should see a new class created in WMI on your PSS called something like sms_g_pnp_signed_driver_custom. You should also be able to query it in a query or collection in the console.
I’ll check my environment at work tomorrow to see exactly what ours looks like.
Were you able to confirm whether you had sms_g_pnp_signed_driver_custom in your sms\site_stc store? I’ve run out of ideas.
Hey Chris, sorry for the delay! I checked with WMIExplorer and do see the class on my PSS. The name is SMS_G_System_PNP_SIGNED_DRIVER_CUSTOM. All the data is there. It sounds like you may have an issue with the class being added to the database and WMI. I would monitor dataldr.log, remove it, and re-add it. Maybe see if other custom classes can be added as well.
Daniel, Did you have to go into the configuration.mof and add this to the added extensions in order for it to write to the sms/site_stc? Reason I ask is due to the Microsoft note below.
“If you’ve manually changed the Configuration.mof file to add custom inventory classes, these changes will be overwritten when you update to version 1602. To keep using custom classes after you update, you must add them to the “Added extensions” section of the Configuration.mof file after you update to 1602.”
https://docs.microsoft.com/en-us/sccm/core/clients/manage/inventory/extend-hardware-inventory
We’re running 1706 not sure about you.
No sir, anything you add via Client Settings gets added automatically. We only edit configuration.mof for RegKey2Mof changes. Anything straight WMI doesn’t need to be added.
Great post Thanks. I copy pasted the script and ran on few machines. The WMI class has been created and in the report also am able to see the driver info of Win 7 machines. However I could not collect info from Win10 physical machines. Is there anything needs to be done for Win 10 environment.
Nothing special, it works for both OS for us. Is the class created in the Win 10 machines? Is your CI set to run on both OS? Are the client settings different for Win10?
Below are the steps which I followed,
Copy the script to powershell ISE in a win7 machine and ran the script manually. I have not created any CI or compliance baseline.
After running the script, class got created and added the class to default client settings
Since I dont want to disturb the default settings, created a custom client settings with only this class and removed it from default client settings
Deployed the custom client settings to a collection which has all types of machines
Got the result from win7 machines. However the class did not get created on Win10 machine.
Am I missing something?
In the machine that didn’t report check inventoryagent.log and see if the class was inventoried when hardware inventory was ran.
In the inventoryagent log the error was Class “Win32 PNP.. custom” does not exist
Ah double check the class name and what you have in hinv. Sounds like it may not match exactly.
Class name is correct. Instead of typing the full name I gave the short form
Class Name in the log is “Win32_PNPSignedDriver_Custom” We did not change anything in the PS script.
If the class name in WMI and in inventoryagent.log match, not sure what else would prevent it from inventorying. It could be a Windows issue or a SCCM issue, not sure. May want to test on a few other Win10 machines to see if they all fail.
To create the class in all the machines for the first time, do we have to deploy the script in each machine once so that the class gets created in all the machines and sends data to the inventory cycle?
Yes, you have to create the custom WMI class some way or another. You also have to rerun it to gather new data when there are changes. The script will delete the class and recreate it with the updated data every time it is ran.
Thanks Daniel.
Its working fine.
Great news!
We are pulling the driver data, but for some reason there is no data being gathered for Universal Serial Bus hardware? Only USB under the System section in Device Manager. Nothing from under Universal Serial Bus section. Anyone have a similar problem?
Check WMI locally, is the data there?
Hi Daniel. Thanks for the reply. Yes it is in WMI. WMI query:
Select * From Win32_PnPSignedDriver Where DeviceName Like “Intel(R) USB 3.0 eXtensible Host Controller” and driverversion < "5.0.4.43"
Select * From Win32_PnPSignedDriver Where DeviceName Like "Intel(R) USB 3.0 eXtensible Host Controller" and DriverVersion < "5.0.3.42"
The next thing I would try is to run your Compliance Item script locally and see what output you get. Does it show the USB drivers?
Our engineer made an update in the script and it now captures the USB controller data. Thanks.
It was probably getting excluded from the CUSTOM WMI class because of this line:
-and $_.DriverProviderName -ne ‘Microsoft’
I found with this enabled it created A LOT of extra entries because of PnP activity using the Generic Microsoft drivers. Such as Keyboard, Mouse and Monitor unplugging and replugging as well as RDP sessions being active at the time the script was ran etc etc.
This didn’t have an overly large impact on the “PN_P_SIGNED_DRIVER_CUSTOM_DATA” table, but it certainly did on the “PN_P_SIGNED_DRIVER_CUSTOM_HIST” – depending on how often you run the CI script in the baseline and how often PnP devices were being modified It’s also worth noting that at one stage I configured the HWInventory to collect the “ScriptLastRan” attribute of the Custom WMI class which caused every line to change in the HWInventory every time and this made the “PN_P_SIGNED_DRIVER_CUSTOM_HIST” table MUCH larder. You can see evidence of this in the Historical View of Resource Explorer as well.
Ah great!
Some joker has basically done a copy and paste of your article to claim as their own – http://www.vikrambedi.com/gathering-driver-information-in-sccm-configuration-manager/
Thanks Lee, I’ll take care of it!
Good Stuff… but Just a thought… I changed
Get-WmiObject win32_pnpsigneddriver -Property DeviceClass, DeviceName,DriverDate,DriverProviderName,DriverVersion,HardwareID,DeviceID |
where{$_.DeviceClass -ne ‘VOLUMESNAPSHOT’ -and $_.DeviceClass -ne ‘LEGACYDRIVER’ -and $_.DriverProviderName -ne ‘Microsoft’ -and $_.DriverVersion -notlike “2:5*”} …
to:
$sFilter=”DeviceID != ‘HTREE\\ROOT\\0’ AND DeviceClass != ‘VOLUMESNAPSHOT’ AND DeviceClass != ‘LEGACYDRIVER’ AND Signer != ‘Microsoft Windows'”;
Get-CimInstance win32_pnpsigneddriver -Filter $sFilter …
As its been some time since the original post, IMO, $_.DriverProviderName -ne ‘Microsoft’ -and $_.DriverVersion -notlike “2:5*”, are possibly no longer the best filters.
Thanks
I would agree. At the time of the post we didn’t have PowerShell v3 out in the environment, so no CIM cmdlets. Thanks for the suggestion!
This was really helpful, thank you. I have managed to implement this and can retreive data from the view created, I would however, like to you use the collected data to create collections based on driver version etc. such that I can deploy updates in a controlled manner. I do not have much experience creating WQL queries and wonder if anyone has used this for the same purpose successfully?
Ah, you do not need to know the WQL, that is just a plus. When you go to create a collection, add a query for the following.
Attribute class: PNP Signed Driver_Custom
Attribute: DeviceName, DriverVersion, or DriverDate
You can filter based on DeviceName and then use DriverVersion or DriverDate to limit what you are looking for.
Excellent, thank you for replying so quickly, I´ve tried it now and it works. This has made my week!
Fantastic!
Hi, about the effect in the database. If my understanding is correct, this would have a great impact if all computers (let’s say 100k computers) have the pnp_signed_driver_custom WMI Class in them, right? If there is no pnp_signed_driver_custom WMI class in the computer, SCCM would not be able to pull data for the driver version and insert it in SCCM’s database.
Furthermore, if only 1 computer among 100k computers have the pnp_signed_driver_custom WMI class, there will only be entries for 1 computer for the pnp_signed_driver_custom data in the SCCM’s database. Is my visualization correct?
Thanks!
Yes, that is correct. For our inventory, we see usually 10-15 entries per machine, so at 100k computers, that would be 1-1.5 million rows. For us, that not is very large. You have to determine what would be acceptable for your environment and database.
Quick observation if I may; the timestamp. Nothing wrong with the $Date variable if your clients are all in one timezone and/or country, but if they’re not then the value and format will not be consistent. It will, by default, be the local client time (without stating UTC offset) and in local client format (e.g., today could be 23/04/2020, 04/23/2020, 23-04-2020, etc.).
So I changed that line to;
$Date = (Get-Date).ToUniversalTime().ToString(“yyyyMMddTHHmmssfffffffZ”)
which will give a consistent time value and format.
May be useful for anyone publishing scripts to not assume date format.
Great suggestion!
Hi Daniel,
Nice article.
Just added the cutom WMI class on our SCCM site server (I found the Win32_PnpSignedDriver_Custom class when searching the class from Hardware Inventory client settings), added all but the view v_gs_pnp_signed_driver_custom is not populated in the CM Database. Also, no info from clients after HW inventory, does the WMI class need to be created on all clients that we need to inventory this custom WMI class ?
Hi Nille, that is correct.
There are two parts, create the class on the clients via script, and then inventory that class with MEMCM. If you run the SQL query for the class on your MEMCM database, and it comes back successfully, but empty, then it was added properly. You just need to run the script on the clients and make sure the custom class is added to your hardware inventory client settings.