Skip to content

Instantly share code, notes, and snippets.

@ishu3101
Created October 4, 2015 03:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ishu3101/e334aaabcd39d27f43de to your computer and use it in GitHub Desktop.
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/
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