List Installed Software aka Get-InstalledSoftware

I needed a script to check for installed software on local and remote machines that did not rely on the Win32_Product WMI class as this will only return software that the windows installer knows about.

One way to do this is via the visual basic script List All Installed Software (Microsoft) on script center, but as I prefer Powershell I had to rewrite my own version.

Also since posting this on technet I have had some feedback that it was not working on everyones machine so please feel free to add questions or feedback here and we can iron out any bugs there maybe.

Also if anyone has any design ideas, as I am not particularly happy about the way the 64 bit version works.

Usage Examples:
Get-InstalledSoftware
Get-InstalledSoftware | Select Name,InstallDate | Format-Table
Get-InstalledSoftware | Sort-Object @{Expression={$_.ComputerName};Ascending=$True},@{Expression={$_.Name};Ascending=$True} | Format-Table
Get-InstalledSoftware "ComputerA","ComputerB" | Export-CSV -NoTypeInformation "C:\InstalledSoftware.csv";

32 Bit

#http://jongurgul.com/blog/installedsoftware/
Function Get-InstalledSoftware{
	Param([String[]]$Computers)
	If (!$Computers) {$Computers = $ENV:ComputerName}
	$Base = New-Object PSObject;
	$Base | Add-Member Noteproperty ComputerName -Value $Null;
	$Base | Add-Member Noteproperty Name -Value $Null;
	$Base | Add-Member Noteproperty Publisher -Value $Null;
	$Base | Add-Member Noteproperty InstallDate -Value $Null;
	$Base | Add-Member Noteproperty EstimatedSize -Value $Null;
	$Base | Add-Member Noteproperty Version -Value $Null;
	$Results =  New-Object System.Collections.Generic.List[System.Object];

	ForEach ($ComputerName in $Computers){
		$Registry = $Null;
		Try{$Registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$ComputerName);}
		Catch{Write-Host -ForegroundColor Red "$($_.Exception.Message)";}

		If ($Registry){
			$UninstallKeys = $Null;
			$SubKey = $Null;
			$UninstallKeys = $Registry.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Uninstall",$False);
			$UninstallKeys.GetSubKeyNames()|%{
				$SubKey = $UninstallKeys.OpenSubKey($_,$False);
				$DisplayName = $SubKey.GetValue("DisplayName");
				If ($DisplayName.Length -gt 0){
					$Entry = $Base | Select-Object *
					$Entry.ComputerName = $ComputerName;
					$Entry.Name = $DisplayName.Trim();
					$Entry.Publisher = $SubKey.GetValue("Publisher");
					[ref]$ParsedInstallDate = Get-Date
					If ([DateTime]::TryParseExact($SubKey.GetValue("InstallDate"),"yyyyMMdd",$Null,[System.Globalization.DateTimeStyles]::None,$ParsedInstallDate)){
					$Entry.InstallDate = $ParsedInstallDate.Value
					}
					$Entry.EstimatedSize = [Math]::Round($SubKey.GetValue("EstimatedSize")/1KB,1);
					$Entry.Version = $SubKey.GetValue("DisplayVersion");
					[Void]$Results.Add($Entry);
				}
			}
		}
	}
	$Results
}

64 Bit

#http://jongurgul.com/blog/installedsoftware/
Function Get-InstalledSoftware{
	Param([String[]]$Computers)
	If (!$Computers) {$Computers = $ENV:ComputerName}
	$Base = New-Object PSObject;
	$Base | Add-Member Noteproperty ComputerName -Value $Null;
	$Base | Add-Member Noteproperty Name -Value $Null;
	$Base | Add-Member Noteproperty Publisher -Value $Null;
	$Base | Add-Member Noteproperty InstallDate -Value $Null;
	$Base | Add-Member Noteproperty EstimatedSize -Value $Null;
	$Base | Add-Member Noteproperty Version -Value $Null;
	$Base | Add-Member Noteproperty Wow6432Node -Value $Null;
	$Results =  New-Object System.Collections.Generic.List[System.Object];

	ForEach ($ComputerName in $Computers){
		$Registry = $Null;
		Try{$Registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine,$ComputerName);}
		Catch{Write-Host -ForegroundColor Red "$($_.Exception.Message)";}

		If ($Registry){
			$UninstallKeys = $Null;
			$SubKey = $Null;
			$UninstallKeys = $Registry.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Uninstall",$False);
			$UninstallKeys.GetSubKeyNames()|%{
				$SubKey = $UninstallKeys.OpenSubKey($_,$False);
				$DisplayName = $SubKey.GetValue("DisplayName");
				If ($DisplayName.Length -gt 0){
					$Entry = $Base | Select-Object *
					$Entry.ComputerName = $ComputerName;
					$Entry.Name = $DisplayName.Trim();
					$Entry.Publisher = $SubKey.GetValue("Publisher");
					[ref]$ParsedInstallDate = Get-Date
					If ([DateTime]::TryParseExact($SubKey.GetValue("InstallDate"),"yyyyMMdd",$Null,[System.Globalization.DateTimeStyles]::None,$ParsedInstallDate)){
					$Entry.InstallDate = $ParsedInstallDate.Value
					}
					$Entry.EstimatedSize = [Math]::Round($SubKey.GetValue("EstimatedSize")/1KB,1);
					$Entry.Version = $SubKey.GetValue("DisplayVersion");
					[Void]$Results.Add($Entry);
				}
			}

				If ([IntPtr]::Size -eq 8){
                $UninstallKeysWow6432Node = $Null;
                $SubKeyWow6432Node = $Null;
                $UninstallKeysWow6432Node = $Registry.OpenSubKey("Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall",$False);
                    If ($UninstallKeysWow6432Node) {
                        $UninstallKeysWow6432Node.GetSubKeyNames()|%{
                        $SubKeyWow6432Node = $UninstallKeysWow6432Node.OpenSubKey($_,$False);
                        $DisplayName = $SubKeyWow6432Node.GetValue("DisplayName");
                        If ($DisplayName.Length -gt 0){
                        	$Entry = $Base | Select-Object *
                            $Entry.ComputerName = $ComputerName;
                            $Entry.Name = $DisplayName.Trim();
                            $Entry.Publisher = $SubKeyWow6432Node.GetValue("Publisher");
                            [ref]$ParsedInstallDate = Get-Date
                            If ([DateTime]::TryParseExact($SubKeyWow6432Node.GetValue("InstallDate"),"yyyyMMdd",$Null,[System.Globalization.DateTimeStyles]::None,$ParsedInstallDate)){
                            $Entry.InstallDate = $ParsedInstallDate.Value
                            }
                            $Entry.EstimatedSize = [Math]::Round($SubKeyWow6432Node.GetValue("EstimatedSize")/1KB,1);
                            $Entry.Version = $SubKeyWow6432Node.GetValue("DisplayVersion");
                            $Entry.Wow6432Node = $True;
                            [Void]$Results.Add($Entry);
                        	}
                        }
                	}
                }
		}
	}
	$Results
}

http://gallery.technet.microsoft.com/scriptcenter/519e1d3a-6318-4e3d-b507-692e962c6666

2 thoughts on “List Installed Software aka Get-InstalledSoftware

Leave a Reply