Skip to content

Instantly share code, notes, and snippets.

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 HumanEquivalentUnit/9b3c2067464bd9cee2733c6d692d91ce to your computer and use it in GitHub Desktop.
Save HumanEquivalentUnit/9b3c2067464bd9cee2733c6d692d91ce to your computer and use it in GitHub Desktop.
using namespace System.Collections.Generic
using namespace System.Management.Automation
using namespace System.Security.AccessControl
using namespace Microsoft.Win32
function Get-InstalledSoftware {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
[ValidateNotNullOrEmpty()]
[SupportsWildcards()]
[string] $Name
)
begin {
$allNames = $null
}
process {
if (-not $PSBoundParameters.ContainsKey('Name') -or [string]::IsNullOrEmpty($Name)) {
return
}
if ($null -eq $allNames) {
$startingCapacity = 1
if ($MyInvocation.ExpectingInput) {
$startingCapacity = 4
}
$allNames = [List[string]]::new($startingCapacity)
}
$allNames.Add($Name)
}
end {
if ($null -ne $allNames) {
$wildcards = [WildcardPattern[]]::new($allNames.Count)
for ($i = 0; $i -lt $allNames.Count; $i++) {
$wildcards[$i] = [WildcardPattern]::new(
$allNames[$i],
[WildcardOptions]::IgnoreCase)
}
}
# Don't use the registry provider for performance and to allow us to open the
# 64 bit registry view from a 32 bit process.
$hklm = $null
$ownsKey = $false
try {
$registryPaths = (
@{
Path = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'
Is64Bit = $true
},
@{
Path = 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall'
Is64Bit = $false
})
$hklm = [Registry]::LocalMachine
if (-not [Environment]::Is64BitProcess) {
if ([Environment]::Is64BitOperatingSystem) {
$ownsKey = $true
$hklm = [RegistryKey]::OpenBaseKey(
[RegistryHive]::LocalMachine,
[RegistryView]::Registry64)
} else {
$registryPaths = @($registryPaths[0])
$registryPaths[0].Is64Bit = $false
}
}
foreach ($registryPath in $registryPaths) {
$software = $null
try {
$software = $hklm.OpenSubKey($registryPath.Path)
foreach ($subKeyName in $software.GetSubKeyNames()) {
$subKey = $null
try {
$subKey = $software.OpenSubKey(
$subKeyName,
[RegistryRights]::QueryValues)
$displayName = $subKey.GetValue('DisplayName')
if ([string]::IsNullOrEmpty($displayName)) {
continue
}
if ($wildcards.Length -gt 0) {
$wasMatchFound = $false
foreach ($wildcard in $wildcards) {
if ($wildcard.IsMatch($displayName)) {
$wasMatchFound = $true
break
}
}
if (-not $wasMatchFound) {
continue
}
}
$installedOn = $subKey.GetValue('InstallDate')
if (-not [string]::IsNullOrWhiteSpace($installedOn)) {
$installedOn = [datetime]::ParseExact($installedOn, 'yyyyMMdd', $null)
}
# yield
[PSCustomObject]@{
PSTypeName = 'Utility.InstalledSoftware'
Name = $displayName
Publisher = $subKey.GetValue('Publisher')
DisplayVersion = $subKey.GetValue('DisplayVersion')
Uninstall = $subKey.GetValue('UninstallString')
Guid = $subKeyName
InstallDate = $installedOn
Is64Bit = $registryPath.Is64Bit
PSPath = 'Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\{0}\{1}' -f (
$registryPath.Path,
$subKeyName)
}
} catch {
$PSCmdlet.WriteError($PSItem)
} finally {
if ($null -ne $subKey) {
$subKey.Dispose()
}
}
}
} finally {
if ($null -ne $software) {
$software.Dispose()
}
}
}
} finally {
if ($ownsKey -and $null -ne $hklm) {
$hklm.Dispose()
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment