Auflisten installierter Software mit PowerShell: Ein kostenloses Tool

Wenn Sie ein Systemadministrator sind, gehört es zu Ihren Aufgaben, Software auf vielen Systemen zu installieren, zu aktualisieren und zu entfernen. Was wäre, wenn ich Ihnen sagen würde, dass Sie sich nicht mehr mit jedem einzelnen Computer verbinden und manuell nach installierter Software suchen müssen? Sie können tatsächlich mit PowerShell installierte Software auflisten!

In diesem Blogbeitrag zeige ich Ihnen, wie Sie mit PowerShell installierte Software auf Ihrem lokalen Computer und vielen Computern gleichzeitig auflisten können.

Listing installed software with PowerShell script

Beachten Sie, dass einige Artikel Ihnen möglicherweise vorschlagen, etwas wie Get-WmiObject -Class win32_product zu tun. Tun Sie das nicht. Erfahren Sie hier, warum ..

Installierte Software und die Registry

Zur Referenz: Installierte Software befindet sich an drei Orten:

  • dem 32-Bit-Systemdeinstallations-Registrierungsschlüssel
  • dem 64-Bit-Systemdeinstallations-Registrierungsschlüssel
  • dem Deinstallations-Registrierungsschlüssel jedes Benutzerprofils.

Jeder Softwareeintrag wird in der Regel durch die global eindeutige Kennung (GUID) der Software definiert. Der Innenbereich des GUID-Schlüssels enthält alle Informationen zu dieser bestimmten Software. Um eine vollständige Liste zu erhalten, muss PowerShell jeden dieser Schlüssel aufzählen, jeden Registrierungswert lesen und die Ergebnisse analysieren.

Da der Code zum korrekten Parsen dieser Werte viel mehr Platz benötigt als ein einzelner Artikel bieten kann, habe ich eine vorab erstellte Funktion namens Get-InstalledSoftware erstellt, um installierte Software mit PowerShell aufzulisten, die diesen Code für Sie zusammenfasst, wie Sie unten sehen können, der installierte Programme auf einem Computer auflistet.

function Get-InstalledSoftware {
    <#
	.SYNOPSIS
		Ruft eine Liste aller auf einem Windows-Computer installierten Software ab.
	.BEISPIEL
		PS> Get-InstalledSoftware
		
		Dieses Beispiel ruft alle auf dem lokalen Computer installierte Software ab.
	.PARAMETER ComputerName
		Wenn Sie einen Remote-Computer abfragen, verwenden Sie hier den Computernamen.
	
	.PARAMETER Name
		Den Titel der Software, auf den Sie die Abfrage beschränken möchten.
	
	.PARAMETER Guid
		Die Software-GUID, auf die Sie die Abfrage beschränken möchten.
	#>
    [CmdletBinding()]
    param (
		
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$ComputerName = $env:COMPUTERNAME,
		
        [Parameter()]
        [ValidateNotNullOrEmpty()]
        [string]$Name,
		
        [Parameter()]
        [guid]$Guid
    )
    process {
        try {
            $scriptBlock = {
                $args[0].GetEnumerator() | ForEach-Object { New-Variable -Name $_.Key -Value $_.Value }
				
                $UninstallKeys = @(
                    "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall",
                    "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
                )
                New-PSDrive -Name HKU -PSProvider Registry -Root Registry::HKEY_USERS | Out-Null
                $UninstallKeys += Get-ChildItem HKU: | where { $_.Name -match 'S-\d-\d+-(\d+-){1,14}\d+$' } | foreach {
                    "HKU:\$($_.PSChildName)\Software\Microsoft\Windows\CurrentVersion\Uninstall"
                }
                if (-not $UninstallKeys) {
                    Write-Warning -Message 'No software registry keys found'
                } else {
                    foreach ($UninstallKey in $UninstallKeys) {
                        $friendlyNames = @{
                            'DisplayName'    = 'Name'
                            'DisplayVersion' = 'Version'
                        }
                        Write-Verbose -Message "Checking uninstall key [$($UninstallKey)]"
                        if ($Name) {
                            $WhereBlock = { $_.GetValue('DisplayName') -like "$Name*" }
                        } elseif ($GUID) {
                            $WhereBlock = { $_.PsChildName -eq $Guid.Guid }
                        } else {
                            $WhereBlock = { $_.GetValue('DisplayName') }
                        }
                        $SwKeys = Get-ChildItem -Path $UninstallKey -ErrorAction SilentlyContinue | Where-Object $WhereBlock
                        if (-not $SwKeys) {
                            Write-Verbose -Message "No software keys in uninstall key $UninstallKey"
                        } else {
                            foreach ($SwKey in $SwKeys) {
                                $output = @{ }
                                foreach ($ValName in $SwKey.GetValueNames()) {
                                    if ($ValName -ne 'Version') {
                                        $output.InstallLocation = ''
                                        if ($ValName -eq 'InstallLocation' -and 
                                            ($SwKey.GetValue($ValName)) -and 
                                            (@('C:', 'C:\Windows', 'C:\Windows\System32', 'C:\Windows\SysWOW64') -notcontains $SwKey.GetValue($ValName).TrimEnd('\'))) {
                                            $output.InstallLocation = $SwKey.GetValue($ValName).TrimEnd('\')
                                        }
                                        [string]$ValData = $SwKey.GetValue($ValName)
                                        if ($friendlyNames[$ValName]) {
                                            $output[$friendlyNames[$ValName]] = $ValData.Trim() ## Einige Registrierungswerte haben abschließende Leerzeichen.
                                        } else {
                                            $output[$ValName] = $ValData.Trim() ## Einige Registrierungswerte haben abschließende Leerzeichen.
                                        }
                                    }
                                }
                                $output.GUID = ''
                                if ($SwKey.PSChildName -match '\b[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}\b') {
                                    $output.GUID = $SwKey.PSChildName
                                }
                                New-Object -TypeName PSObject -Prop $output
                            }
                        }
                    }
                }
            }
			
            if ($ComputerName -eq $env:COMPUTERNAME) {
                & $scriptBlock $PSBoundParameters
            } else {
                Invoke-Command -ComputerName $ComputerName -ScriptBlock $scriptBlock -ArgumentList $PSBoundParameters
            }
        } catch {
            Write-Error -Message "Error: $($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)"
        }
    }
}

Sobald Sie diese Funktion in Ihre PowerShell-Konsole kopieren und einfügen oder sie Ihrem Skript hinzufügen, können Sie sie mit einem bestimmten Computernamen über den ComputerName-Parameter aufrufen.

Liste installierter Software mit PowerShell

PS> Get-InstalledSoftware -ComputerName XXXXX

Wenn Sie dies tun, erhalten Sie für jedes installierte Softwarestück ein Objekt zurück. Sie können eine Fülle von Informationen über diese installierte Software abrufen.

Wenn Sie den Softwaretitel im Voraus kennen, können Sie auch den Parameter Name verwenden, um nur die Software zu begrenzen, die diesem Wert entspricht.

Zum Beispiel möchten Sie vielleicht nur überprüfen, ob Microsoft Visual C++ 2005 Redistributable (x64) installiert ist. Sie würden dies einfach als Wert für den Name-Parameter verwenden, wie unten gezeigt.

PS> Get-InstalledSoftware -ComputerName MYCOMPUTER -Name 'Microsoft VisualC++ 2005 Redistributable (x64)'

Zusammenfassung

Mit PowerShell können Sie eine vollständig kostenlose Tool erstellen, mit dem Sie und Ihr Team einfach installierte Software auf vielen Windows-Computern gleichzeitig finden können!

Source:
https://adamtheautomator.com/powershell-list-installed-software/