Reputation: 27
I have a script to get a list of all installed software using the registry keys. But when I check the list, some entries don't have a name or version shown. Below is my script:
## Include CSV file of all computers with header "pc"
$computers = Import-Csv "C:\Users\P1334126\Documents\Test.CSV"
$array = @()
#Define the variable to hold the location of Currently Installed Programs
foreach($pc in $computers) {
$computername=$pc.computername
$UninstallKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
#Create an instance of the Registry Object and open the HKLM base key
$reg = [microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine', $computername)
#Drill down into the Uninstall key using the OpenSubKey Method
$regkey = $reg.OpenSubKey($UninstallKey)
#Retrieve an array of string that contain all the subkey names
$subkeys = $regkey.GetSubKeyNames()
#Open each Subkey and use GetValue Method to return the required values for each
foreach($key in $subkeys) {
$thisKey=$UninstallKey + '\\' + $key
$thisSubKey=$reg.OpenSubKey($thisKey)
$obj = New-Object PSObject
$obj | Add-Member -MemberType NoteProperty -Name 'ComputerName' -Value $computername
$obj | Add-Member -MemberType NoteProperty -Name 'DisplayName' -Value $($thisSubKey.GetValue("DisplayName"))
$obj | Add-Member -MemberType NoteProperty -Name 'DisplayVersion' -Value $($thisSubKey.GetValue("DisplayVersion"))
$obj | Add-Member -MemberType NoteProperty -Name 'Publisher' -Value $($thisSubKey.GetValue("Publisher"))
$array += $obj
}
}
$array | Select-Object ComputerName, DisplayName, DisplayVersion, Publisher | Sort-Object -Property
ComputerName | Out-File InstalledSoftware.txt
As shown in the picture below, some names and versions are misssing, is there a reason for this? Appreciate the help.
Upvotes: 1
Views: 2035
Reputation: 61188
You really should avoid collecting stuff in an array using +=
syntax as it completely recreates the array on every iteration. It makes the code slow and is memory consuming.
Also, I would advise to Close the registry keys you have opened after you're done with them.
As for output, you are currently saving the results to a simple text file, but I think (since you have gathered nice objects) outputting to CSV file would be better as this preserves the info as readable data you can open in Excel for instance.
Your code revised:
# Include CSV file of all computers with header "pc"
$computers = Import-Csv "C:\Users\P1334126\Documents\Test.CSV"
# probe these two registry paths
$UninstallPaths = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall'
# Collect info of Currently Installed Programs
$array = foreach ($pc in $computers) {
$computername = $pc.computername
# Create an instance of the Registry Object and open the HKLM base key
$regHKLM = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computername)
foreach ($UninstallKey in $UninstallPaths) {
# Drill down into the Uninstall key using the OpenSubKey Method
$regkey = $regHKLM.OpenSubKey($UninstallKey)
# the computer may not have the 'Wow6432Node' registry key
if (!$regkey) { break }
# Retrieve an array of string that contain all the subkey names
$subkeys = $regkey.GetSubKeyNames()
# Open each Subkey and use GetValue Method to return the required values for each
foreach($key in ($regkey.GetSubKeyNames())) {
$thisPath = Join-Path -Path $UninstallKey -ChildPath $key
$thisSubKey = $regHKLM.OpenSubKey($thisPath)
# we want to output only if there is at least a DisplayName to show
$displayName = $thisSubKey.GetValue("DisplayName")
if (![string]::IsNullOrWhiteSpace($displayName)) {
# output a PSObject to be collected in variable $array
# the order of the properties also defines the order of the fields in the output
[PsCustomObject] @{
ComputerName = $computername
DisplayName = $displayName
DisplayVersion = $thisSubKey.GetValue("DisplayVersion")
Publisher = $thisSubKey.GetValue("Publisher")
# if you want to know the registry path aswell, uncomment the next entry
# RegistryPath = $thisPath
}
}
# close the subkey
$thisSubKey.Close()
}
# close the $regKey
$regkey.Close()
}
# close the base key
$regHKLM.Close()
}
# sort on ComputerName
$array = $array | Sort-Object -Property ComputerName
# output on screen
$array | Format-Table -AutoSize
# or if you prefer
$array | Out-GridView -Title 'InstalledSoftware'
# output to CSV file you can open in Excel
$array | Export-Csv -Path 'InstalledSoftware.csv' -NoTypeInformation
Upvotes: 1
Reputation: 27516
Instead of the registry you can use this to list installed software in powershell 5.1:
get-package
Upvotes: 1