Get the GUID list of installed programs

There was a thread this month on the mailing list where a member shared a list of GUIDs installed in his environment.

Later on, he also shared how he got it. I won’t blame him, I also used to be a WMIC guy before I discovered and learned Powershell.
Let’s just take a minute to see what (hassle) he went through:

I’m glad that so many people found the GUID list useful. Obtaining it didn’t take me too long, I used the following in a batch script and ran it on all of the machines on our network. The temp file keeps one machine from locking the master file while it queries. This is the script I used to grab it all:

@echo off
wmic product get identifyingnumber,name,vendor,version /FORMAT:csv | find "{" > "%temp%\%computername%-GUID.tmp"
type "%temp%\%computername%-GUID.tmp" >> "\\<SERVERNAME>\<SHARENAME>\GUID-MasterList.csv"
del "%temp%\%computername%-GUID.tmp"

I opened it in Excel, removed the first column (when exporting to CSV format it appends the hostname), saved it as a CSV (ignore the warning that you may lose some formatting if you don’t save it as a spreadsheet), and then used gVim -c “:sort u” GUID-MasterList.csv to remove redundant lines (or Notepad++ with TextFX plugin installed under TextFX Tools for a GUI method).

I tried experimenting with a way to strip the hostname from the file and sort it entirely command-line but I realized that I was starting to waste the time I just saved myself. That’s for another day. Along with fixing issues where a comma in the Vendor field will cause it to split in two values. I end up saving it as a spreadsheet anyway, so it’s only cosmetic.


Don’t say you’re too busy, you’ve wasted enough time. Just invest in teaching yourself Powershell and be confident that it will for sure save your time sooner or later.

Why WMIC isn’t a good idea?
Well the first line of code proposed, just don’t run on my computer 😦

To solve it I had to specify the fullpath of XSL file like this:

Then it doesn’t perform very fast.
We can compare the equivalent of the WMIC commandline

wmic --% product GET identifyingnumber,name,vendor,version /FORMAT:"C:\Windows\system32\wbem\en-US\csv.xsl"

to the WMI query performed in Powershell that will produce the same output

Get-WmiObject -Class win32_Product -Property identifyingnumber,name,vendor,version | ForEach-Object {
    '{0},{1},{2},{3},{4}' -f $env:COMPUTERNAME,$_.identifyingnumber,$_.Name,$_.Vendor,$_.Version

As you can see Powershell doesn’t perform that much faster.
In both cases, 10 seconds it’s far too much, don’t you think?

Now, let’s see the huge flexibility PowerShell delivers over WMIC by solving the following issues:

  1. Get rid of the computername in front of each line.
  2. Remove or replace the comma in the Vendor field
  3. Perform faster
  • Get rid of the computername in front of each line.
  • That’s easy as you don’t have this problem in Powershell:

    $properties = "identifyingnumber","name","vendor","version"            
    Get-WmiObject -Class win32_Product -Property $properties |             
    Select -Property $properties
  • Remove or replace the comma in the Vendor field
  • Idem in Powershell, you don’t have this problem. All you need to do to get a CSV format is to use the built-in cmdlet designed for this purpose and send the WMI objects selected through the pipeline like this:

    $properties = "identifyingnumber","name","vendor","version"            
    Get-WmiObject -Class win32_Product -Property $properties |             
    Select -Property $properties |             
    Export-Csv -Path C:\GUID.csv -Encoding Unicode -NoTypeInformation

    Then, in Excel, you do

    Select the file C:\Guid.csv,

    Select the delimiter ‘comma’ instead of default ‘tab’ and leave the text qualifier to “quote”

    As you can see in the following capture, I haven’t the problem and some vendors have a comma in their name.

  • Perform faster
  • Well 10 seconds to get the list of products is a huge amount of time. Let’s say that WMI isn’t the best approach as it performs too slowly.
    I can actually divide by 20 the execution time by directly gathering the information from the registry like this:

    $properties = "identifyingnumber","name","vendor","version"
    Get-ChildItem HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\*\Products | ForEach-Object {
        $root  = $_.PsPath
        $_.GetSubKeyNames() | ForEach-Object {
            try {
                $RegKeyPath = (Join-Path -Path (Join-Path -Path $root -ChildPath $_) -ChildPath InstallProperties)
                $obj = Get-ItemProperty -Path $RegKeyPath -ErrorAction Stop
                if ($obj.UninstallString) {
                        Path = $RegKeyPath;
                        Name = $obj.DisplayName ;
                        Vendor = $obj.Publisher ;
                        Version = $obj.DisplayVersion ; 
                        IdentifyingNumber = ($obj.UninstallString -replace "msiexec\.exe\s/[IX]{1}","")
            } catch {
    } | Select -Property $properties

    CQFD 😀

Fix for Get-ADUser or Get-ADComputer throwing error “One or more properties are invalid.”

About four days ago, the update rollup of March 2014 for Windows 8.1 or Windows Server 2012 R2 was released. This bundle contains KB2923122 that aims at fixing the following error:

Get-ADUser : One or more properties are invalid.
Parameter name: msDS-AssignedAuthNPolicy

While the workarounds were easy,

  1. you could either specify the list of properties (consider this as a solution for automation because it performs faster)
  2. (…and I only have ~70 computers in AD)

  3. or you could pipe it to the Get-ADObject cmdlet
  4. Get-ADUser administrator | Get-ADObject -Properties *
  5. or upgrade the schema to version 69 (see this post)
  6. Get-ADObject (dir AD:\ | Where Name -eq "Schema").DistinguishedName -Properties objectVersion

… it got finally fixed by either the above standalone hotfix or update rollup 😀

I’ve applied the update rollup to my workstation and here’s how to see what KB was applied:

Get-HotFix -Id "KB2928680"            
Get-HotFix | ? HotfixId -match "2923122"