Pregunta

¿Existe una manera sencilla de conectarse al estándar?Añadir o eliminar programas'funcionalidad usando PowerShell para desinstalar una aplicación existente?¿O para comprobar si la aplicación está instalada?

¿Fue útil?

Solución

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

$app.Uninstall()

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

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

Otros consejos

EDITAR:A lo largo de los años, esta respuesta ha recibido 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 el siguiente script, 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éntete libre de editar.
  2. Si MSI no instala la aplicación, no funciona.La razón por la que se escribió a continuación es porque modifica el MSI para desinstalar sin intervención, lo que no siempre es el caso predeterminado cuando se usa la cadena de desinstalación nativa.

Usar el objeto WMI lleva una eternidad.Esto es muy rápido si sólo conoce el nombre del programa 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 corregir el segundo método en la publicación de Jeff Hillman, puedes hacer lo siguiente:

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

O

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

Para agregar un poco a esta publicación, necesitaba poder eliminar software de múltiples servidores.Usé la respuesta de Jeff para llevarme a esto:

Primero obtuve una lista de servidores, usé un ANUNCIO consulta, pero puede proporcionar la variedad de nombres de computadoras como desee:

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

Luego los recorrí y agregué 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()
}

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

Descubrí que la clase Win32_Product no se recomienda porque desencadena reparaciones y no está optimizada para consultas. Fuente

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

Úselo así:. 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"}
 }
function Uninstall-App {
    Write-Output "Uninstalling $($args[0])"
    foreach($obj in Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall") {
        $dname = $obj.GetValue("DisplayName")
        if ($dname -contains $args[0]) {
            $uninstString = $obj.GetValue("UninstallString")
            foreach ($line in $uninstString) {
                $found = $line -match '(\{.+\}).*'
                If ($found) {
                    $appid = $matches[1]
                    Write-Output $appid
                    start-process "msiexec.exe" -arg "/X $appid /qb" -Wait
                }
            }
        }
    }
}

Llámalo de esta manera:

Uninstall-App "Autodesk Revit DB Link 2019"

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 resulte útil.

Tenga en cuenta que le debo a David Stetler el crédito por este guión, ya que está basado 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"

Una línea de código:

get-package *notepad* |% { & $_.Meta.Attributes["UninstallString"]}

Basado en la respuesta de Jeff Hillman:

Aquí tienes una función que puedes añadir a tu 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 + "'")
    }
}

Digamos que deseas desinstalar Bloc de notas++.Simplemente escribe esto en PowerShell:

> uninstall("notepad++")

Sólo ten en cuenta que Get-WmiObject Puede llevar algo de tiempo, ¡así que tenga paciencia!

Usar:

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 está completamente probado, pero se ejecutó con PowerShell 4.

Ejecuté el archivo PS1 como se ve aquí.Permitiéndole recuperar todos los sistemas del ANUNCIO e intentar desinstalar varias aplicaciones en todos los sistemas.

He utilizado el Número de identificación para buscar la causa del software de la entrada de David Stetler.

No probado:

  1. No agregar identificadores a la llamada de la función en el script, sino iniciar el script con identificadores de parámetros
  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. Uso de direcciones IP para conectarse al sistema

Lo que no:

  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 desinstalar().Al intentarlo, recibí un error que me decía que no es posible llamar a un método para una expresión que tiene un valor NULL.En su lugar, utilicé Remove-WmiObject, que parece lograr lo mismo.

PRECAUCIÓN:Sin un nombre de computadora dado, elimina el software de TODO sistemas en Active Directory.

Para la mayoría de mis programas, los scripts de esta publicación hicieron el trabajo.Pero tuve que enfrentarme a un programa heredado que no podía eliminar usando msiexec.exe o la clase Win32_Product.(por alguna razón obtuve la salida 0 pero el programa 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 del archivo exe de desinstalación:

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

Tendrás que limpiar la cadena de resultado:

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

ahora cuando tengas lo relevante ruta del archivo exe de desinstalación del programa puedes 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 se pueden ejecutar de forma remota. Lo hice usando el comando invocar, pero creo que agregar el argumento -nombredecomputadora puede funcionar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top