Listar el software instalado con PowerShell Quick (en 30 segundos)
Si es administrador de sistemas, uno de sus trabajos es instalar, actualizar y eliminar software de muchos sistemas. ¿Qué pasaría si te dijera que ya no tienes que conectarte a cada máquina y verificar manualmente el software instalado? ¡De hecho, puedes enumerar el software instalado con PowerShell!
En esta publicación de blog, le mostraré cómo enumerar el software instalado con PowerShell en su máquina local y en muchas computadoras a la vez.
Tenga en cuenta que algunos artículos pueden indicarle que haga algo como
Get-WmiObject -Class win32_product. No hagas eso. Descubra por qué aquí.
Software instalado y el registro
Como referencia, el software instalado existe en tres ubicaciones:
- la clave de registro de desinstalación del sistema de 32 bits
- la clave de registro de desinstalación del sistema de 64 bits
- la clave de registro de desinstalación de cada perfil de usuario.
Cada entrada de software suele estar definida por el identificador único global (GUID) del software. El interior de la clave GUID contiene toda la información sobre ese software en particular. Para obtener una lista completa, PowerShell debe enumerar cada una de estas claves, leer cada valor del registro y analizar los resultados.
Dado que el código para analizar correctamente estos valores es mucho más de lo que un solo artículo puede contener, he creado previamente una función llamada Get-InstalledSoftware para enumerar el software instalado con PowerShell que resume todo ese código para usted. como puede ver a continuación, enumera los programas instalados en una computadora.
function Get-InstalledSoftware {
<#
.SYNOPSIS
Retrieves a list of all software installed on a Windows computer.
.EXAMPLE
PS> Get-InstalledSoftware
This example retrieves all software installed on the local computer.
.PARAMETER ComputerName
If querying a remote computer, use the computer name here.
.PARAMETER Name
The software title you'd like to limit the query to.
.PARAMETER Guid
The software GUID you'e like to limit the query to
#>
[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() ## Some registry values have trailing spaces.
} else {
$output[$ValName] = $ValData.Trim() ## Some registry values trailing spaces
}
}
}
$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 vez que copie y pegue esta función en su consola de PowerShell o la agregue a su secuencia de comandos, puede llamarla usando un nombre de computadora en particular con el parámetro ComputerName.
Listar el software instalado con PowerShell
PS> Get-InstalledSoftware -ComputerName XXXXXCuando haga esto, obtendrá un objeto por cada software que esté instalado. Puede obtener una gran cantidad de información sobre esto independientemente del software que esté instalado.
Si conoce el título del software de antemano, también puede utilizar el parámetro Name para limitar solo el software que coincida con ese valor.
Por ejemplo, tal vez sólo desee comprobar si Microsoft Visual C++ 2005 Redistributable (x64) está instalado. Simplemente usaría esto como el valor del parámetro Name como se muestra a continuación.
PS> Get-InstalledSoftware -ComputerName MYCOMPUTER -Name 'Microsoft VisualC++ 2005 Redistributable (x64)'Resumen
Al usar PowerShell para instalar el software, puede crear una herramienta completamente gratuita que usted y su equipo pueden usar para encontrar fácilmente el software instalado en muchas computadoras con Windows a la vez.
