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
Leave a Reply