Every so often, I need to find an installed program.  Until now, I’ve just been typing appwiz.cpl in my cmd.exe or PowerShell.exe window, but that’s inefficient.  Moreover, when I have to scan for the given build of a product deployed across the lab, that’s just painful.

 

Get-InstalledMsi | ? { $_.displayname -match 'office' } | Select-Object -Property computername,
  displayname, displayversion | fl


ComputerName   : TIMDUNN-W520
DisplayName    : Microsoft Visual Studio 2010 Tools for Office Runtime (x64)
DisplayVersion : 10.0.40303

ComputerName   : TIMDUNN-W520
DisplayName    : Microsoft Office Professional Plus 2013 - en-us
DisplayVersion : 15.0.4496.1000

(etc.)

Here’s the function.

function Get-InstalledMsi {
     param (
         [String[]]$computerName = @( $env:computerName )
     );
    
     try {
         foreach ($computer in $computerName) {
        
             # open remote registry
             $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computer);
             $regKey = $reg.OpenSubKey('Software\Microsoft\Windows\CurrentVersion\Uninstall');
            
             # if successful
             if ($regKey) {
            
                 # get list of all installed programs
                 $installed = $regKey.GetSubKeyNames() | % {
                     $output = New-Object -TypeName PsObject;
                     Add-Member -MemberType ScriptMethod -Name AddNote -value { 
                         Add-Member -MemberType NoteProperty -Name $args[0] -Value $args[1] -InputObject $this | Out-Null
                     } -InputObject $output | Out-Null;
                    
                     $output.AddNote('ComputerName', $computer);
                     $subkey = $regKey.OpenSubKey($_);
                     if ($subkey) {
                         $subkey.GetValueNames() | % { if ($_) { $output.AddNote($_, $subkey.GetValue($_)); } }
                         if ($output.DisplayName) { $output; }
                     }
                 }
                
                 #get list of all properties from all installed programs
                 $property = @();
                 $installed | % {
                     Get-Member -InputObject $_ -MemberType NoteProperty | % { if ([array]::IndexOf($property, $_.name) -eq -1) { $property += $_.name; } }
                 }
                
                 #output list of all installed programs with all properties from above.
                 $installed | % {
                     $output = $_;
                     $property | % { if ($output.$_ -eq $null) { $output.AddNote($_, $null); } }
                     $output;
                 }
             }
         }
     }
     catch  { Write-Warning "Insert error handling here." }
}