Earlier this month I posted about getting the installed updates and/or hotfixes.
This got me thinking… what about installed software?
If you want to compare servers to each other, installed software may be just as important as installed updates and/or hotfixes.
However, the first step would be to get the installed software. Only after that, we’ll be able to compare them…
So, here we go. This time I’m not using PowerShell remoting, simply because there is no need to.
Remote WMI is just fine for this
function Get-InstalledSoftware { param ( [parameter(mandatory=$true)][array]$ComputerName ) foreach ($Computer in $ComputerName) { Get-WmiObject -ComputerName $Computer Win32Reg_AddRemovePrograms | Where-Object {$_.DisplayName -ne $null} | foreach { $Object = New-Object -TypeName PSObject $Object | Add-Member -MemberType noteproperty -Name 'Name' -Value $_.DisplayName $Object | Add-Member -MemberType noteproperty -name 'ComputerName' -value $Computer $Object } } }
My next post will be a function that utilizes the function above in order to compare installed software between devices.
*** EDIT ***
As Dave Wyatt pointed out in the comments, the above function doesn’t always work, for example on a x64 system. Next to that, the used WMI class isn’t available on all systems. This is a pesky little issue if you expect the function to work in all situations, which it should.
So Dave mentioned registry keys that could be used, so here is the updated function:
function Get-InstalledSoftware { param ( [parameter(mandatory=$true)][array]$ComputerName ) foreach ($Computer in $ComputerName) { $OSArchitecture = (Get-WMIObject -ComputerName $Computer win32_operatingSystem -ErrorAction Stop).OSArchitecture if ($OSArchitecture -like '*64*') { $RegistryPath = 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' } else { $RegistryPath = 'Software\Microsoft\Windows\CurrentVersion\Uninstall' } $Registry = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $Computer) $RegistryKey = $Registry.OpenSubKey("$RegistryPath") $RegistryKey.GetSubKeyNames() | foreach { $Registry.OpenSubKey("$RegistryPath\$_") | Where-Object {($_.GetValue("DisplayName") -notmatch '(KB[0-9]{6,7})') -and ($_.GetValue("DisplayName") -ne $null)} | foreach { $Object = New-Object -TypeName PSObject $Object | Add-Member -MemberType noteproperty -Name 'Name' -Value $($_.GetValue("DisplayName")) $Object | Add-Member -MemberType noteproperty -name 'ComputerName' -value $Computer $Object } } } }