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


Comments

18 responses to “List Installed Software aka Get-InstalledSoftware”

  1. jack Avatar
    jack

    Great script. Thanks!!

  2. treeckomon Avatar
    treeckomon

    now experimenting with this script and trying to upload results to sql database.
    only issue is when outputting 64 bit results to sql database I only see 8 items, but when outputting results to csv file I get 32 items.

Leave a Reply

Your email address will not be published. Required fields are marked *