In general terms I never recommend to use WMI filters with Group Policy Object, and there are many reasons for this including

  • When WMI database is corrupt the filter may deliver a inconsistent result
  • ServiceDesk may not understand when a GPO should apply and not
  • May slow down computer startups
  • May slow down logon phases

But when WMI filters are used correctly there are benefits, like during a Windows migration phase to apply different user GPOs based on where the user logged on. Normally users should be allowed to logon to different operating systems and this will make sure different set of policies applies based on users operating system. WMI filters based on computer objects I find hard argue for, computer installations are more or less static, better to create an organizational unit for each operating system and move the object to the correct OU during installation.

Looking from a performance perspective it is important to optimize your WMI queries, so how do we do that? First of all, we need a way to measure the time it takes to process the query. If you don’t know it yet you will discover there are many classes that are really slow and there are small tips to optimize the query you already written.

Use this sample PowerShell script to measure the execution time of your queries. It will run the query 100 times and show the result of average, maximum and minimum time.

This script will query for operating system Windows 10

$q = ‘Select * From Win32_OperatingSystem Where Version LIKE “10.0.%”‘
$a = for ($i = 1; $i -le 100; $i++) {
Measure-Command -Expression {
Get-WmiObject -Query $q
}
};
$a | Measure-Object TotalMilliseconds -Sum -Average -Maximum –Minimum

The result? Average of 26,6 Milliseconds.
image

Let’s try something else, query for an install application like Silverlight 5.1

$q = ‘Select * From Win32_Product Where IdentifyingNumber = “{89F4137D-6C26-4A84-BDB8-2E5A4BB71E00}”‘
$a = for ($i = 1; $i -le 100; $i++) {
Measure-Command -Expression {
Get-WmiObject –Query $q
}
};
$a | Measure-Object TotalMilliseconds -Average -Maximum -Minimum

Guess what? This is a slow class and should generally not be used, it takes about 1519,4 Milliseconds or 1,5194 seconds to execute this query.
image

Can I do anything to optimize these queries? Yes, a normal WMI query starts with Select * From, replace the * with the same attribute in your Where cause. See example below

$q = ‘Select Version From Win32_OperatingSystem Where Version LIKE “10.0.%”‘

This almost cut the time in half!
image

$q = ‘Select IdentifyingNumber From Win32_Product Where IdentifyingNumber = “{89F4137D-6C26-4A84-BDB8-2E5A4BB71E00}”‘

What happend now? In this example it didn’t have that much performance impact, more or less no difference.
image

Let’s replace the attribute with some other, for example Caption to see if that gives us any benefits

$q = ‘Select Caption From Win32_Product Where IdentifyingNumber = “{89F4137D-6C26-4A84-BDB8-2E5A4BB71E00}”‘

Still no bigger difference, but it is better. Average 1256,0 Milliseconds

Some other examples

Query for a Windows feature

$q = ‘Select * from Win32_OptionalFeature Where Name = “NetFx3” And InstallState = 2’

Average: 549,8 Milliseconds

$q = ‘Select Name from Win32_OptionalFeature Where Name = “NetFx3” And InstallState = 2’

Average: 582,8 Milliseconds

$q = ‘Select InstallState from Win32_OptionalFeature Where Name = “NetFx3” And InstallState = 2’

Average: 344,5 Milliseconds

Query for service

$q = ‘Select * From Win32_Service Where Name = “AppVClient” And Started = TRUE’

Average: 149,7 Milliseconds

$q = ‘Select Started From Win32_Service Where Name = “AppVClient” And Started = TRUE’

Average: 21,4 Milliseconds

$q = ‘Select * From Win32_Directory Where Name = “c:\\Program Files\\Active Directory Rights Management Services Client 2.1″‘

Average: 11,3 Milliseconds

Some general warnings

There are some queries that you should not use, this can be WMI classes that are really slow or just the attributes that you choose to filter on. Here are two warnings, based on files and folders filters.

$q = ‘Select * From Win32_Directory Where Caption = “c:\\Program Files\\Active Directory Rights Management Services Client 2.1″‘

Average: 35394,1 Milliseconds, that’s 35 seconds when using this class wrong!

$q = ‘Select * From CIM_DataFile Where Name Like “c:\\Program Files\\Active Directory Rights Management Services Client 2.1\\msipc.dll”‘;

Just don’t use it Smile This query will enumerate all files on your drive and your disk will look like this, and the query take ages

image

 

Note! This is not an exact science when building your queries, queries will take different about of time to execute based on your environment like hardware, operating system, software installed etc. But use this as a baseline when building your queries.

Advertisements