Udostępnij za pośrednictwem


Detecting which Windows Optional Components are installed in a machine

I have been experimenting with programmatic detection of Windows Optional Components installed with Component Based Servicing(available in Windows Vista/2008 and Windows 7/2008R2).

This is similar to using the wizards in the Roles and Features applets of Server Manager, but doing it from a script or executable program.

Installing optional components is easy. OCSetup is included in the operating system and all you need to do is give it a package name

Detecting components was surprisingly less straightforward. Windows Server Core includes OCList.exe that will output a tree view of all components (very useful for viewing dependencies among components) and list their installed state. This is pretty close to what I needed but it had 2 small problems:

  • OCList is currently unavailable on the non-core versions of Windows Server (it can be copied from a Server Core installation, but I prefer avoiding this kind of external dependency)
  • I would have to parse the output from OCList (which I didn’t like either because it can break too easily after an OS upgrade)

I had a quick look at the OCList sources (to see if I could use the same techniques) but it was full of currently undocumented APIs (e.g., using the ICbsPackage interface). For legal reasons if I wanted to call these APIs from my code I would have to wait until they are publicly documented, which I didn’t want to do.

My lead suggested looking in WMI and after some digging I finally found the Win32_OptionalFeature WMI class that provides the info that I need and it can be scripted or accessed programmatically.

For example, listing the currently installed optional components can be done in PowerShell with:

foreach ($feature in Get-WmiObject -Class Win32_OptionalFeature -Namespace root\CIMV2 -Filter "InstallState = 1") {$feature.Name}

Listing the components that are available and not yet installed can be done by comparing the InstallState to 2 (instead of 1)

Querying the state of specific components is also easy. For example, finding out if .Net 3.0 is installed would be:

(Get-WmiObject -Class Win32_OptionalFeature -Namespace root\CIMV2 -Filter "Name = 'NetFx3'").InstallState

and the possible results are:

  • Null = Not available (or wrong name)
  • 1 = Installed
  • 2 = Available but not installed

The reference for WQL (WMI Query Language) is here.

If you need to write managed code or native code to do this type of WMI queries, my recommendation is to experiment with PowerShell first and then implement it in your target language once you have found the best queries.