¿Cómo puedo desinstalar una aplicación usando PowerShell?

¿Existe una forma simple de conectar la funcionalidad estándar de ” Agregar o quitar progtwigs ” utilizando PowerShell para desinstalar una aplicación existente ? ¿O para verificar si la aplicación está instalada?

$app = Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -match "Software Name" } $app.Uninstall() 

Editar: Rob encontró otra manera de hacerlo con el parámetro Filtro:

 $app = Get-WmiObject -Class Win32_Product ` -Filter "Name = 'Software Name'" 

Para arreglar el segundo método en la publicación de Jeff Hillman, puedes hacer un:

 $app = Get-WmiObject -Query "SELECT * FROM Win32_Product WHERE Name = 'Software Name'" 

O

 $app = Get-WmiObject -Class Win32_Product ` -Filter "Name = 'Software Name'" 

EDITAR: A lo largo de los años, esta respuesta ha obtenido bastantes votos a favor. Me gustaría agregar algunos comentarios. No he usado PowerShell desde entonces, pero recuerdo haber observado algunos problemas:

  1. Si hay más coincidencias que 1 para la secuencia de comandos siguiente, no funciona y debe agregar el filtro de PowerShell que limita los resultados a 1. Creo que es -First 1 pero no estoy seguro. Siéntase libre de editar.
  2. Si la aplicación no está instalada por MSI, no funciona. La razón por la que se escribió a continuación es porque modifica el MSI para desinstalar sin intervención, que no siempre es el caso predeterminado cuando se utiliza la cadena de desinstalación nativa.

Usar el objeto WMI toma para siempre. Esto es muy rápido si solo conoce el nombre del progtwig que desea desinstalar.

 $uninstall32 = gci "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match "SOFTWARE NAME" } | select UninstallString $uninstall64 = gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match "SOFTWARE NAME" } | select UninstallString if ($uninstall64) { $uninstall64 = $uninstall64.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X","" $uninstall64 = $uninstall64.Trim() Write "Uninstalling..." start-process "msiexec.exe" -arg "/X $uninstall64 /qb" -Wait} if ($uninstall32) { $uninstall32 = $uninstall32.UninstallString -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X","" $uninstall32 = $uninstall32.Trim() Write "Uninstalling..." start-process "msiexec.exe" -arg "/X $uninstall32 /qb" -Wait} 

Para agregar un poco a esta publicación, necesitaba poder eliminar el software de varios servidores. Usé la respuesta de Jeff para guiarme a esto:

Primero obtuve una lista de servidores, utilicé una consulta de AD , pero puede proporcionar la matriz de nombres de computadora como quiera:

 $computers = @("computer1", "computer2", "computer3") 

Luego hice un bucle a través de ellos, agregando el parámetro -computer a la consulta gwmi:

 foreach($server in $computers){ $app = Get-WmiObject -Class Win32_Product -computer $server | Where-Object { $_.IdentifyingNumber -match "5A5F312145AE-0252130-432C34-9D89-1" } $app.Uninstall() } 

Usé la propiedad IdentifyingNumber para comparar en lugar de nombre, solo para asegurarme de que estaba desinstalando la aplicación correcta.

Descubrí que no se recomienda la clase Win32_Product porque desencadena reparaciones y no se optimiza la consulta. Fuente

Encontré esta publicación de Sitaram Pamarthi con un script para desinstalar si conoces la guía de la aplicación. También proporciona otro script para buscar aplicaciones realmente rápido aquí .

Úselo de la siguiente manera:. \ Uninstall.ps1 -GUID {C9E7751E-88ED-36CF-B610-71A1D262E906}

 [cmdletbinding()] param ( [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)] [string]$ComputerName = $env:computername, [parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true)] [string]$AppGUID ) try { $returnval = ([WMICLASS]"\\$computerName\ROOT\CIMV2:win32_process").Create("msiexec `/x$AppGUID `/norestart `/qn") } catch { write-error "Failed to trigger the uninstallation. Review the error message" $_ exit } switch ($($returnval.returnvalue)){ 0 { "Uninstallation command triggered successfully" } 2 { "You don't have sufficient permissions to trigger the command on $Computer" } 3 { "You don't have sufficient permissions to trigger the command on $Computer" } 8 { "An unknown error has occurred" } 9 { "Path Not Found" } 9 { "Invalid Parameter"} } 

Haré mi pequeña contribución. Necesitaba eliminar una lista de paquetes de la misma computadora. Este es el guión que se me ocurrió.

 $packages = @("package1", "package2", "package3") foreach($package in $packages){ $app = Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -match "$package" } $app.Uninstall() } 

Espero que esto sea útil.

Tenga en cuenta que le debo a David Stetler el mérito de este guión, ya que se basa en el suyo.

Aquí está el script de PowerShell usando msiexec:

 echo "Getting product code" $ProductCode = Get-WmiObject win32_product -Filter "Name='Name of my Software in Add Remove Program Window'" | Select-Object -Expand IdentifyingNumber echo "removing Product" # Out-Null argument is just for keeping the power shell command window waiting for msiexec command to finish else it moves to execute the next echo command & msiexec /x $ProductCode | Out-Null echo "uninstallation finished" 

Según la respuesta de Jeff Hillman:

Aquí hay una función que puede agregar a su profile.ps1 o definir en la sesión actual de PowerShell:

 # Uninstall a Windows program function uninstall($programName) { $app = Get-WmiObject -Class Win32_Product -Filter ("Name = '" + $programName + "'") if($app -ne $null) { $app.Uninstall() } else { echo ("Could not find program '" + $programName + "'") } } 

Supongamos que quiere desinstalar Notepad ++ . Simplemente escriba esto en PowerShell:

> uninstall("notepad++")

Solo ten en cuenta que Get-WmiObject puede llevar algo de tiempo, ¡así que ten paciencia!

Utilizar:

 function remove-HSsoftware{ [cmdletbinding()] param( [parameter(Mandatory=$true, ValuefromPipeline = $true, HelpMessage="IdentifyingNumber can be retrieved with `"get-wmiobject -class win32_product`"")] [ValidatePattern('{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}}')] [string[]]$ids, [parameter(Mandatory=$false, ValuefromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage="Computer name or IP adress to query via WMI")] [Alias('hostname,CN,computername')] [string[]]$computers ) begin {} process{ if($computers -eq $null){ $computers = Get-ADComputer -Filter * | Select dnshostname |%{$_.dnshostname} } foreach($computer in $computers){ foreach($id in $ids){ write-host "Trying to uninstall sofware with ID ", "$id", "from computer ", "$computer" $app = Get-WmiObject -class Win32_Product -Computername "$computer" -Filter "IdentifyingNumber = '$id'" $app | Remove-WmiObject } } } end{}} remove-hssoftware -ids "{8C299CF3-E529-414E-AKD8-68C23BA4CBE8}","{5A9C53A5-FF48-497D-AB86-1F6418B569B9}","{62092246-CFA2-4452-BEDB-62AC4BCE6C26}" 

No se ha probado completamente, pero funcionaba con PowerShell 4.

He ejecutado el archivo PS1 como se ve aquí. Permitiéndole recuperar todos los sistemas del AD e intentando desinstalar múltiples aplicaciones en todos los sistemas.

Utilicé IdentifyingNumber para buscar el software que causa la entrada de David Stetlers.

No probado:

  1. No agregar identificadores a la llamada de la función en el script, sino iniciar el script con ID de parámetro
  2. Llamar al script con más de 1 nombre de computadora no recuperado automáticamente de la función
  3. Recuperando datos de la tubería
  4. Usar direcciones IP para conectarse al sistema

Lo que no hace

  1. No proporciona ninguna información si el software realmente se encontró en un sistema determinado.
  2. No proporciona ninguna información sobre el fracaso o el éxito de la desinstalación.

No pude usar uninstall (). Probé que recibí un error diciéndome que no es posible llamar a un método para una expresión que tiene un valor de NULL. En cambio, utilicé Remove-WmiObject, que parece lograr lo mismo.

PRECAUCIÓN : sin un nombre de computadora dado, elimina el software de TODOS los sistemas en el Directorio Activo.

Para la mayoría de mis progtwigs, los guiones en este Post hicieron el trabajo. Pero tuve que enfrentarme a un progtwig heredado que no pude eliminar utilizando la clase msiexec.exe o Win32_Product. (por alguna razón obtuve la salida 0 pero el progtwig todavía estaba allí)

Mi solución fue usar la clase Win32_Process:

Con la ayuda de nickdnk, este comando es para obtener la ruta de desinstalación del archivo exe:

64 bits:

 [array]$unInstallPathReg= gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match $programName } | select UninstallString 

32 bits:

  [array]$unInstallPathReg= gci "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match $programName } | select UninstallString 

deberás limpiar la cadena de resultados:

 $uninstallPath = $unInstallPathReg[0].UninstallString $uninstallPath = $uninstallPath -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X","" $uninstallPath = $uninstallPath .Trim() 

ahora, cuando tenga la ruta del archivo de desinstalación del progtwig correspondiente , puede usar este comando:

 $uninstallResult = (Get-WMIObject -List -Verbose | Where-Object {$_.Name -eq "Win32_Process"}).InvokeMethod("Create","$unInstallPath") 

$ uninstallResult – tendrá el código de salida. 0 es éxito

los comandos anteriores también pueden ejecutarse de forma remota; lo hice usando el comando invoke, pero creo que agregar el argumento -nombre de la computadora puede funcionar