Matt's ConfigMgr blog

Config Manager, System Center products, scripts and other stuff i find interesting.

June 2011 - Posts

Trigger a SCCM HW Inventory when a program is uninstalled on a client

If you use Configuration Manager to Install or Uninstall a program you can follow the progress via the status messages for the specific advertisement you are running. But what if you want your rapports to show correct data or someone uninstalls a program locally on the machine? Then you wont be aware that the program is missing until the client does its next hardware inventory, this of course depends on your settings but default is 7 days between hardware inventories.

In Windows 7 / 2008 R2 there is a new function that allows you to trigger a task based on a event in the event viewer. But since its not really not interesting to go around to all your machine and make this setting I will rather show how this can be done via Group Policy preferences and built in functions in Windows.

To trigger the actual hardware inventory this command will be used (it should be on one line with no spaces in the GUID):

WMIC.exe /namespace:\\root\ccm path sms_client CALL TriggerSchedule "{00000000-0000-0000-0000-000000000001}" /NOINTERACTIVE

WMIC is a very useful tool that has been part of Windows since at least XP (but using that is another topic) and can be used to control some of the Configuration Manager client tasks.

Basic Task

First of all you need to create a new GPO preference and go to Computer Configuration\Preferences\Control Panel\Scheduled Tasks. Choose Scheduled task (Windows Vista and later). Start by giving it a name and choose what credentials you want to be run under. LogonUser is probably ok, since if they have the rights to uninstall a program the probably can trigger a hardware inventory as well.

Naming your task and setting it to running hidden. Make sure it is configured for “Windows 7”.

Create what should trigger the event, in our case we want to trigger when a program is uninstalled. This is logged in the Application log, the source will be MsiInstaller and the event ID is 1034. Here is a article on technet describing the different event id’s for MsiInstaller.

Create an action that will happen when the task gets trigged.
Program: C:\Windows\System32\wbem\WMIC.exe
Arguments: /namespace:\\root\ccm path sms_client CALL TriggerSchedule "{00000000-0000-0000-0000-000000000001}" /NOINTERACTIVE

When this new GPO is applied to a Win7 system a hardware inventory will be triggered every time a uninstall event is logged in the application log.

There is one thing to notice though, if you use SCCM to uninstall programs (or even install programs that automatically removes old programs) this task will be triggered and making all your machines send hardware inventories to your site server. This could cause a massive amount of data hitting your server at the same time so use this method only on specific machines you want extra quick feedback from.

Advanced Task

If you only want the event to be triggered when the uninstallation is made by a user you could instead create a custom filter. This is a little bit harder and requires some XPath syntax but gives you a more controlled task that isn't triggered by SCCM uninstallations. This can be done since uninstallations made by SCCM is always done by the “System” account if you choose “run this program whether or not a user is logged on”. So basically we make the same task but add a condition saying that the task will only be triggered if the uninstall “is not” done by the system account.

Once again, this only works if you use SCCM to install/uninstall programs as local system, if you have programs advertised to be run “As logged on user” this will also trigger the event and make the clients send HW inventory data to you site systems.

To create an advanced filtering rule you do the same as when you create a basic on, but we you get to the step create trigger do the following:

Choose “Custom” under Settings and click “New Event Filter”.

Click the XML tab and enter your Xpath formated query. I have used the following query, note the ! in "Security[@UserID!='S-1-5-18']]” that is used to filter out the System account from the query:

   1: <QueryList>
   2:   <Query Id="0" Path="Application">
   3:     <Select Path="Application">*[System[Provider[@Name='MsiInstaller'] and (Level=4 or Level=0) and (EventID=1034) and Security[@UserID!='S-1-5-18']]]</Select>
   4:   </Query>
   5: </QueryList>

Using “not” is not a valid Xpath so trying “and not” will give you an error. More info on MSDN here. Also note that if you have a invalid syntax in your Xpath the GPO will not complain so make sure its valid before adding it. If you do your tests directly on a Windows 7 client instead the Windows 7 task scheduler will let you know if your syntax is wrong.

A tip for creating Xpath code is to use the task scheduler in Windows 7. When you create a custom event filter start by filling the values in the Filter tab, when you got a query close to what you want you can click the XML tab and the query you built will be shown in XPath code, from there its much easier to customize your query further.