Wednesday, February 13, 2008

The WMI Filter Contest - are you the knight in shining armor?

Welcome to "The Quest for the Holy Desktop WMI Filter”, this is a global search for what you could call "The Perfect Desktop WMI Filter". A WMI filter which, by using WMI Query Language (WQL), should be able to spot DESKTOP computers only. It should be a general query - meaning it should be possible to use the filter in most Active Directory environments around the globe for Group Policy filtering.

So, what is a desktop really? Well, actually in this case we'll say it's the opposite of a laptop. Hmm, then what is a laptop? Easy enough: a computer with a battery! We've got the WMI filter for finding laptops already:

Select * from Win32_Battery  - don't you just love the simplicity in this query?

This filter will make a computer with a battery respond back with "TRUE" (because the WMI class instance is present), meaning a GPO with this filter will apply to computers with batteries. Simple right? And you might think it's easy to just "turn it around" to find desktops, like:

Select * From Win32_Battery Where Availability != 2
  or
Select * From Win32_Battery Where Availability IS NOT NULL
  or
“Where Not X Like Y” or whatever

Maybe it is, maybe it's not... I think it's pretty damn hard! For spotting laptops we could have tested the classes Win32_PortableBattery, Win32_PCMCIAController, Win32_POTSModem as well - but somehow I think most people will agree, that the "essential ting", which makes a laptop a laptop, is in fact the battery presence!

But, our tests for spotting DESKTOPS only (machines without a battery - yes, I know this will include servers as they a "stationary" too) have not been a success yet! We probably just need the correct syntax? And this is where you get into the picture!

 

Are you able to crack open this nut? There's a cool price!

This all started on a mailing list for Group Policy guys and girls - called GPTalk - created and maintained by Group Policy guru and MVP Darren Mar-Elia - the guy behind GPOguy.com and SDM Software. You can join the list RIGHT HERE and participate in this contest to WIN a free copy of the:

GPExpert™ Troubleshooting Pak 

BUT you have to be the first person to crack this thing, there'll be only ONE WINNER - that could be you!

I'll be evaluating incoming answers - FIFO: "First In First Out" method is used. Hopefully we'll see the most simple solution first - simplicity works, right? Actually I wouldn't know in this case would I...

One important thing! We will ask you kindly to TEST any WMI query submissions before sending them to everybody on the list. During your testing, you should use a tool to verify the WMI filter against a minimum of 2 desktops and 2 laptops. You can use the free WMI Filter Validation Tool to test you WMI filters in your environment. Personally I’m also using Scriptomatic version 2 and WBEMTEST for finding the available classes, items, queries etc.

Please have a look at the "rules" further down!

Why do this? Well, because it's fun - and useful at the same time... When looking at it generally, the purpose of this filter is to say: "I want these user settings to apply, but only when the user logs on to stationary machines". This can be used for a lot of security related setting, eg. in the case where Automatically cached Offline Files/Folders are unwanted on stationary machines for certain users etc. The job of most WMI filters placed on User policies is to limit which machines the policy setting(s) should apply to (even though WMI filters could check for user specific things too). Besides from that it's a nice challenge, we can pretty easily "spot" laptops, as they have batteries – and desktops don’t, but that’s not good enough for Mr. WQL, is it?!

 

Stuff we have tried - and the rules

We’ve been around solutions looking for Win32_SystemEnclosure > ChassisType before - which basically doesn’t work in a WMI filter because that’s an Array (and yes, I've also seen lots of posts on forums out there claiming that particular class is the solution – but for WMI/WQL queries it’s not). If would work in a script (because you can add additional logic to scripts), but we are searching for a WMI Filter - not workarounds of any kind!

As mentioned we tried with the Win32_Battery WMI class. However, as desktops don’t know this class at all, they'll return FALSE no matter what. Basically a desktop computer is gonna say “Heck, I don’t know anything about that class *Panic* I’m out!” – or just “False”... Bummer!

We have also tried PowerSupplyState, Win32_DesktopMonitor, Win32_DisplayConfiguration, Win32_SystemSlot, Win32_Fan and other classes – just haven’t found the perfect “this is definitely a desktop WMI item value or class”…

We're basically looking for something like:

A) Select * from Win32_SomeClassOnlyDesktopsHave

Or

B )Select * from Win32_SomeClass.SomeItem = “SomeValueOnlyDesktopsHave”

Or

C) Some way of saying “if you don’t know the class (eg. Win32_Battery), then apply the GPO anyway”

Again, the “quest” is to find the perfect, *universal*, way of spotting “Non-laptops” or Desktops – it can of course be done by looking for some special computer Manufacturer/Model, BIOS version, specific hardware driver or whatever – but that stuff it most likely gonna be different from environment to environment. Also, if we all just used computer names like “DESKxxx” for desktops and “LAPTxxx” for laptops, we could have used WMI filters for computer name – but unfortunately that’s not the case - or at least I won't consider that a valid solution :)

The thing is, that normally it’s the LAPTOPS that have special hardware – like Batteries and built-in Modems, PCMCIA slots etc. – so they are pretty easy to find. With desktop computers it’s another story – hope you can help us out here!

Please, again, we know lot’s of “workarounds”, but what we need is a *WMI filter* and it has to return *TRUE* for *DESKTOPS* (or let’s call the NON-LAPTOPS or NON-PORTABLES, it doesn’t really matter).

Remember, simplicity works - maybe the answer/solution is pretty straight forward? Feel free to post any additional questions to the mailing list!

 

Another example of what has been tried

We could maybe try to go for presence of PCI (and not Mini-PCI) or AGP slots, as we expect most desktops to have PCI slots (and laptops to have Mini-PCI, but that would depend on the form factor) – or maybe AGP (but does onboard VGA count as AGP? Any PCI VGA cards left out there? Yeah, probably...). If not we could maybe go for something like this:

A) Select * From Win32_SystemSlot Where SlotDesignation = “PCI%”
Or
B) Select * From Win32_SystemSlot Where SlotDesignation = “AGP”

However, this is not accepted as a solution as we cannot say that all desktop computers have AGP slots. But - maybe you can convince us otherwise?

 

Other cool Group Policy information:

You'll find additional Group Policy information at these sites:

www.gpanswers.com - The home of Group Policy guru and MVP Jeremy Moskowitz, check out the community there too!
TechNet Group Policy Forum - A brand new Group Policy forum on Microsoft TechNet
The Group Policy Team - The home of the Microsoft Group Policy Team
Jakob H. Heidelberg blog - My own blog, mostly about Group Policy and Security
www.heidelbergit.dk - My website with blog RSS, certifications, LinkedIn info etc.

 

Hope to hear from you soon - O' Yee Knight of the Microsoft Group Policy Table!

13 Comments:

Scott said...

Thanks a lot for this post. I'm currently using group membership to push down our wireless policy to laptops. This looks like a much better was of doing it. Very helpful.

Chris Knight said...

'select * from Win32_Battery' isn't a valid WMI query for determining a laptop.

This query will return true for any desktop with a UPS connected via USB that registers itself as a battery with the PnP manager.

If the WMI Query is used for the sole purpose of Group Policy processing then simply make life easier for yourself and either:

- use a standardised computer naming convention, or
- create security groups or OUs for computers to differentiate this (computer groups are more flexible)

While I applaud the efforts to try and come up with a bulletproof way of determining laptop and desktop systems, Microsoft and hardware vendors haven't made this easy. I'd suggest path of least resistance is the mot sensible approach here.

Jakob H. Heidelberg said...

Chris - there are LOTS of workarounds, and regular GPO filtering is not part of the contest here.

The whole idea of this contest was to find a WMI filter fot the job - and I think we nailed it! MemoryFormfactor!

This is a nice solution I think:
Select * from Win32_PhysicalMemory where FormFactor != 12

More info on that WMI class:
http://msdn2.microsoft.com/en-us/library/aa394347%28VS.85%29.aspx

If you want a laptop go for:
Select * from Win32_PhysicalMemory where FormFactor = 12

Now, there's no such things as a buletproof WMI filter - and we knoe that - the Quest was/is to find something close to 99%. These queries depend on hardware - and hardware is not just hardware...

And BTW - you cannot use regular GPO filtering for this purpose - a WMI filter can do more than that (read my blog again). A WMI filter can limit on which MACHINES a given GPO with USER policy settings will process.

Thanx for the comment!

itismike said...

Just a heads up - this doesn't work on some Dell laptops because they return a FormFactor of "8".

Sebastian said...

Thanks a lot for this solution!

@itismike
Could be useful to filter the memorytype.IMO the following memorytypes are not relevant so they could be excluded:

10 ROM
11 Flash
12 EEPROM
13 FEPROM
14 EPROM

HP Desktops return the formfactor "8" for the memory modules and "0" for System ROM. Perhaps it's similar with Dell Laptops. The System ROM returns "11" (Flash) for memorytype.

e.g. the following line only returns the formfactor of the installed memory modules on my HP dc7800:

wmic path win32_physicalmemory where(memorytype!=10 and memorytype!=11 and memorytype!=12 and memorytype!=13 and memorytype!=14) get formfactor

Check which module returns "8" on your dell laptop with the following line:

wmic path win32_physicalmemory get devicelocator,formfactor,memorytype

(sorry I'm not so firm with SQL so I used the command line)

GiZmO said...

Wouldn't it be possible to use Win32_ComputerSystem PCSystemType class for this purpose?

/GiZmO

GiZmO said...

Wouldn't it be possible to use Win32_ComputerSystem PCSystemType class for this purpose?

/GiZmO

itismike said...

@GiZmO
the Win32_ComputerSystem PCSystemType class is only available on Vista. Unfortunately our environment is not Vista, nor is it mono-culture.

I nominate Chris Knight to be the 'knight' in shining armor. Windows and hardware vendors made this task impossible to automate. In the words of the WOPR: "The only winning move is...not to play."

Brian said...

Unfortunately, I've discovered that if your desktop has a UPS installed - it has a battery! Consider monkey wrench properly applied....

itismike said...

Chassis type is more reliable. I have a query saved on my other PC that I can update this with when I get back.

Nick said...

We run Dell's, and you cannot use the PhysicalMemory trick as they report as an 8.

However, you CAN use check the model to determine if you it's a desktop (or conversely a laptop)

Select * from Win32_ComputerSystem where Model like '%Optiplex%' or Model like '%Precision%'

Chris Rowson said...

Laptops generally have SODIMM memory and desktops have DIMM memory. You can therefore test for a desktop by testing for the presence of a DIMM

"Select * from Win32_PhysicalMemory WHERE (FormFactor = 8)"

8 for DIMMs 12 for SODIMMs

Unknown said...

Note that Win32_PhysicalMemory does not seem to exist on virtual machines.