Elencare il software installato con PowerShell: uno strumento gratuito

Se sei un amministratore di sistema, uno dei tuoi compiti è installare, aggiornare e rimuovere software da molti sistemi. E se ti dicessi che non devi più connetterti a ogni macchina e controllare manualmente il software installato? In realtà, puoi elencare il software installato con PowerShell!

In questo articolo, ti mostrerò come elencare il software installato con PowerShell sulla tua macchina locale e su molte macchine contemporaneamente.

Listing installed software with PowerShell script

Nota che alcuni articoli possono suggerirti di utilizzare un comando come Get-WmiObject -Class win32_product. Non farlo. Scopri perché qui.

Software installato e Registro di sistema

A titolo informativo, il software installato si trova in tre posizioni:

  • la chiave di registro di disinstallazione del sistema a 32 bit
  • la chiave di registro di disinstallazione del sistema a 64 bit
  • la chiave di registro di disinstallazione del profilo utente.

Generalmente, ogni voce di software è definita dall’identificatore univoco globale (GUID) del software. All’interno della chiave GUID sono contenute tutte le informazioni su quel particolare software. Per ottenere un elenco completo, PowerShell deve enumerare ciascuna di queste chiavi, leggere ciascun valore del Registro di sistema e analizzare i risultati.

Poiché il codice per analizzare correttamente questi valori è molto più grande di quanto possa contenere un singolo articolo, ho già creato una funzione chiamata Get-InstalledSoftware per elencare il software installato con PowerShell che avvolge tutto quel codice per te, come puoi vedere di seguito che elenca i programmi installati su un computer.

function Get-InstalledSoftware {
    <#
	.SINTESI
		Ottiene un elenco di tutto il software installato su un computer Windows.
	.ESEMPIO
		PS> Get-InstalledSoftware
		
		Questo esempio recupera tutto il software installato sul computer locale.
	.PARAMETRO ComputerName
		Se si interroga un computer remoto, utilizzare qui il nome del computer.
	
	.PARAMETRO Name
		Il titolo del software su cui si desidera limitare la query.
	
	.PARAMETRO Guid
		Il GUID del software su cui si desidera limitare la query.
	#>
    [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() ## Alcuni valori del registro hanno spazi finali.
                                        } else {
                                            $output[$ValName] = $ValData.Trim() ## Alcuni valori del registro hanno spazi finali
                                        }
                                    }
                                }
                                $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)"
        }
    }
}

Una volta copiata e incollata questa funzione nella console di PowerShell o aggiunta allo script, è possibile chiamarla utilizzando un nome di computer particolare con il parametro ComputerName.

Elenco del Software Installato con PowerShell

PS> Get-InstalledSoftware -ComputerName XXXXX

Quando lo fai, otterrai un oggetto per ciascun pezzo di software installato. Puoi ottenere una grande quantità di informazioni su qualunque software sia installato.

Se conosci il titolo del software in anticipo, puoi anche utilizzare il parametro Name per limitare la ricerca solo al software che corrisponde a quel valore.

Ad esempio, forse desideri verificare solo se è installato Microsoft Visual C++ 2005 Redistributable (x64). Basterà utilizzare questo valore come parametro Name, come mostrato di seguito.

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

Riassunto

Utilizzando PowerShell per ottenere informazioni sul software installato, puoi creare uno strumento completamente gratuito che tu e il tuo team potrete utilizzare per trovare facilmente il software installato su molti computer Windows contemporaneamente!

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