Skip to content

Querying component information

Heath Stewart edited this page Feb 19, 2018 · 1 revision

Enumerate all components on the machine

You can enumerate all components installed on a system, though on systems with many products installed this may take some time:

get-msicomponentinfo

You can limit the components to one or more products using a filter:

$productCodes = get-msiproductinfo -name "*Visual Studio*" | select -expand ProductCode
get-msicomponentinfo | where { $productCodes -contains $_.ProductCode }

This will still take some time because all components must still be enumerated given how Windows Installer stores information about components. But there is a faster way:

You can select all the components from a product package and then query for them to avoid enumerating all other components on the system.

get-msiproductinfo -name "*Visual Studio*" | foreach { $_ | get-msitable -table Component | add-member -type NoteProperty -name ProductCode -value $_.ProductCode -passthru } | get-msicomponentinfo

Find all shared components on the machine

Shared components are components with the same GUID and target install location installed by more than one client (product). You can find all shared components on a system using get-msisharedcomponentinfo, which is an advanced function exported as a cmdlet.

get-msisharedcomponentinfo

This cmdlet will take some time to run since it must first enumerate all components and then group them.

While you can use a filter to find higher incidences of shared components, you can more easily specify the minimum number of clients that installed any component:

get-msisharedcomponentinfo -count 4

This would select all components installed by 4 or more client products.

Find which product installed a file

You can enumerate all components on the system and find any components that match a particular file or registry key path.

get-msicomponentinfo | where { $_.Path -eq "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe" } | get-msiproductinfo

Registry key paths are a little trickier. Windows Installer stores the path in a proprietary way that is neither documented (though discoverable) or intuitive. But you can use the PSPath property to compare objects.

$reg = gi HKLM:\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\Setup
get-msicomponentinfo | where { $_.PSPath -eq $reg.PSPath } | get-msiproductinfo

On 64-bit machines, the registry path may not be mapped correctly. For example, when running under a 32-bit PowerShell process Windows Installer will still return registry key paths for 64-bit components but those registry key paths are not accessible to PowerShell. When running under 64-bit processes, any 32-bit component path needs to be properly mapped to the WOW64 registry pseudo-hive. So for older releases, the example above may not work correctly.

Clone this wiki locally