Created
October 4, 2015 03:18
-
-
Save ishu3101/e334aaabcd39d27f43de to your computer and use it in GitHub Desktop.
Get Installed Software on Windows. Taken from: http://www.indented.co.uk/2014/01/15/get-installedsoftware/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-InstalledSoftware { | |
# .SYNOPSIS | |
# Get all installed from the Uninstall keys in the registry. | |
# .DESCRIPTION | |
# Read a list of installed software from each Uninstall key. | |
# | |
# This method provides an alternative to using the WMI class Win32_Product which causes an msi reconfiguration action. | |
# | |
# This CmdLet assumes the user is authenticated. | |
# .PARAMETER ComputerName | |
# The computer to execute against. By default, Get-InstalledSoftware reads registry keys on the local computer. | |
# .PARAMETER StartRemoteRegistry | |
# The script should attempt to start the remote registry service if it is not already running. This parameter will only take effect if the service is not disabled. | |
# .PARAMETER IncludeLoadedUserHives | |
# Some software packages, such as DropBox install into a users profile rather than into shared areas. Get-InstalledSoftware can increase the search to include each loaded user hive. | |
# | |
# If a registry hive is not loaded it cannot be searched, this is a limitation of this search style. | |
# .PARAMETER IncludeBlankNames | |
# By default Get-InstalledSoftware will suppress the display of entries with minimal information. If no DisplayName is set it will be hidden from view. This behaviour may be changed using this parameter. | |
# .PARAMETER DebugConnection | |
# By default error messages are suppressed. A large number of errors may be returned by a single device because of the granular nature of registry permissions. This parameter allows the displays of all caught exceptions for debugging purposes. | |
# .EXAMPLE | |
# Get-InstalledSoftware | |
# | |
# Get the list of installed applications from the local computer. | |
# .EXAMPLE | |
# Get-InstalledSoftware -IncludeLoadedUserHives | |
# | |
# Get the list of installed applications from the local computer, including each loaded user hive. | |
# .EXAMPLE | |
# Get-InstalledSoftware -ComputerName None -DebugConnection | |
# | |
# Display all error messages thrown when attempting to audit the specified computer. | |
# .EXAMPLE | |
# Get-InstalledSoftware -IncludeBlankNames | |
# | |
# Display all results, including those with very limited information. | |
[CmdLetBinding()] | |
param( | |
[Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[String]$ComputerName = $Env:ComputerName, | |
[Switch]$StartRemoteRegistry, | |
[Switch]$IncludeLoadedUserHives, | |
[Switch]$IncludeBlankNames, | |
[Switch]$DebugConnection | |
) | |
process { | |
# If the remote registry service is stopped before this script runs it will be stopped again afterwards. | |
if ($StartRemoteRegistry) { | |
$ShouldStop = $false | |
$Service = Get-WmiObject Win32_Service -Filter "Name='RemoteRegistry'" -Computer $ComputerName | |
If ($Service.State -eq "Stopped" -And $Service.StartMode -ne "Disabled") { | |
$ShouldStop = $true | |
$Service.StartService() | Out-Null | |
} | |
} | |
# Create an array to hold open base keys. The Uninstall key should be relative and fixed from here. | |
$BaseKeys = @() | |
if ($IncludeLoadedUserHives) { | |
try { | |
$BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("Users", $ComputerName) | |
} catch [Exception] { | |
if ($DebugConnection) { | |
$Message = $_.Exception.Message -replace "`n" | |
Write-Error "ComputerName: $ComputerName :: $Message :: Users" | |
} | |
} | |
if ($?) { | |
$BaseKey.GetSubKeyNames() | ForEach-Object { | |
$SubKeyName = $_ | |
try { | |
$BaseKeys += $BaseKey.OpenSubKey($SubKeyName) | |
} catch [Exception] { | |
if ($DebugConnection) { | |
$Message = $_.Exception.Message -replace "`n" | |
Write-Error "ComputerName: $ComputerName :: $Message :: $SubKeyName" | |
} | |
} | |
} | |
} | |
} | |
# Connect to the base key | |
try { | |
$BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $ComputerName) | |
} catch [Exception] { | |
if ($DebugConnection) { | |
$Message = $_.Exception.Message -replace "`n" | |
Write-Error "ComputerName: $ComputerName :: $Message :: LocalMachine" | |
} | |
} | |
if ($?) { | |
$BaseKeys += $BaseKey | |
} | |
# Begin reading package information from the registry | |
$Packages = @{} | |
$BaseKeys | ForEach-Object { | |
$BaseKey = $_ | |
# Uninstall keys relative to each base. | |
"Software\Microsoft\Windows\CurrentVersion\Uninstall", "Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object { | |
$UninstallKeyString = $_ | |
try { | |
$UninstallKey = $BaseKey.OpenSubKey($UninstallKeyString) | |
} catch [Exception] { | |
if ($DebugConnection) { | |
$Message = $_.Exception.Message -replace "`n" | |
Write-Error "ComputerName: $ComputerName :: $Message :: LocalMachine\$UninstallKeyString" | |
} | |
} | |
if ($? -and $UninstallKey) { | |
$UninstallKey.GetSubKeyNames() | ForEach-Object { | |
$SubKeyName = $_ | |
$UninstallKey.OpenSubKey($_) | ForEach-Object { | |
# Create a new record for this package | |
if ($Packages.Contains($SubKeyName)) { | |
[Array]$Packages[$SubKeyName].RegistryKeys += "$($BaseKey.ToString())\$UninstallKeyString" | |
} else { | |
$DateString = $_.GetValue("InstallDate"); $InstallDate = $null | |
if ($DateString) { | |
$InstallDate = [DateTime]::ParseExact($DateString, "yyyyMMdd", [Globalization.CultureInfo]::CurrentCulture) | |
} | |
$Package = New-Object PsObject -Property ([Ordered]@{ | |
ComputerName = $ComputerName; | |
Name = $_.GetValue("DisplayName"); | |
DisplayVersion = $_.GetValue("DisplayVersion"); | |
InstallDate = $InstallDate; | |
InstallLocation = $_.GetValue("InstallLocation"); | |
HelpLink = $_.GetValue("HelpLink"); | |
Publisher = $_.GetValue("Publisher"); | |
UninstallString = $_.GetValue("UninstallString"); | |
URLInfoAbout = $_.GetValue("URLInfoAbout"); | |
KeyName = $SubKeyName; | |
RegistryKeys = "$($BaseKey.ToString())\$UninstallKeyString"; | |
InstalledAs = ""; | |
}) | |
$Packages.Add($SubKeyName, $Package) | |
} | |
} | |
} | |
} | |
} | |
} | |
# Attempt to resolve SID strings to something a bit more friendly. This method is a bit limited. | |
$InstalledAs = @{} | |
$Packages.Values | | |
ForEach-Object { $_.RegistryKeys } | | |
Select-Object -Unique | | |
ForEach-Object { | |
if ($_ -match '^HKEY_LOCAL_MACHINE') { | |
if ($_ -match 'Wow6432Node') { | |
$InstalledAs.Add($_, "LocalMachine\64Bit") | |
} else { | |
$InstalledAs.Add($_, "LocalMachine\32Bit") | |
} | |
} elseif ($_ -match '^HKEY_USERS\\(?<SID>[^\\]+)') { | |
$NTAccount = (New-Object Security.Principal.SecurityIdentifier $matches.SID).Translate([Security.Principal.NTAccount]).Value | |
if ($NTAccount) { | |
$InstalledAs.Add($_, $NTAccount) | |
} else { | |
$InstalledAs.Add($_, $matches.SID) | |
} | |
} | |
} | |
$Packages.Keys | ForEach-Object { | |
$Packages[$_].InstalledAs = ($Packages[$_].RegistryKeys | ForEach-Object { $InstalledAs[$_] }) | |
} | |
# Stop the remote registry service if required | |
if ($StartRemoteRegistry -and $ShouldStop) { | |
$Service.StopService() | Out-Null | |
} | |
# Output filtering | |
if ($IncludeBlankNames) { | |
return $Packages.Values | |
} else { | |
return ($Packages.Values | Where-Object Name) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment