web-dev-qa-db-de.com

Wie kann ich eine Anwendung mithilfe von PowerShell deinstallieren?

Gibt es eine einfache Möglichkeit, die Standardfunktion 'Programme hinzufügen oder entfernen' mithilfe von PowerShell an vorhandene Anwendung deinstallieren zu koppeln? Oder um zu überprüfen, ob die Anwendung installiert ist?

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

$app.Uninstall()

Edit: Rob hat eine andere Möglichkeit gefunden, dies mit dem Filter-Parameter zu tun:

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

EDIT: Im Laufe der Jahre hat diese Antwort einige positive Bewertungen erhalten. Ich möchte einige Kommentare hinzufügen. Ich habe PowerShell seitdem nicht mehr verwendet, erinnere mich aber an einige Probleme:

  1. Wenn für das folgende Skript mehr Übereinstimmungen als 1 vorhanden sind, funktioniert es nicht und Sie müssen den PowerShell-Filter anhängen, der die Ergebnisse auf 1 begrenzt. Ich glaube, es ist -First 1, aber ich bin nicht sicher. Fühlen Sie sich frei zu bearbeiten.
  2. Wenn die Anwendung nicht von MSI installiert wird, funktioniert sie nicht. Der Grund dafür wurde wie folgt geschrieben, da MSI ohne Intervention deinstalliert wird. Dies ist bei Verwendung der systemeigenen Deinstallationszeichenfolge nicht immer der Standardfall.

Die Verwendung des WMI-Objekts dauert ewig. Dies ist sehr schnell, wenn Sie nur den Namen des Programms kennen, das Sie deinstallieren möchten.

$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}
38
nickdnk

Um die zweite Methode in Jeff Hillmans Beitrag zu korrigieren, können Sie entweder Folgendes tun:

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

Oder

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

Um diesem Beitrag etwas hinzuzufügen, musste ich Software von mehreren Servern entfernen können. Ich habe Jeffs Antwort verwendet, um mich dazu zu führen:

Zuerst habe ich eine Liste von Servern erhalten, ich habe eine AD -abfrage verwendet, aber Sie können das Array von Computernamen nach Ihren Wünschen angeben:

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

Dann habe ich sie durchlaufen und den Parameter -computer der gwmi-Abfrage hinzugefügt:

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

Ich habe die IdentifyingNumber-Eigenschaft anstelle des Namens verwendet, um sicherzugehen, dass ich die richtige Anwendung deinstallierte.

7
David Stetler

Ich habe herausgefunden, dass die Klasse Win32_Product nicht empfohlen wird, da sie Reparaturen auslöst und die Abfrage nicht optimiert wird. Quelle

Ich habe this post von Sitaram Pamarthi mit einem zu deinstallierenden Skript gefunden, wenn Sie die App-Guid kennen. Er bietet auch ein anderes Skript an, mit dem nach Apps gesucht werden kann here .

Verwenden Sie wie folgt:.\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"}
 }
6
Ricardo

Ich werde meinen eigenen kleinen Beitrag leisten. Ich musste eine Liste von Paketen von demselben Computer entfernen. Dies ist das Skript, das ich mir ausgedacht habe.

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

Ich hoffe das erweist sich als nützlich.

Beachten Sie, dass ich David Stetler die Anerkennung für dieses Skript schulde, da es auf seinem basiert.

3
Ben Key

Hier ist das PowerShell-Skript, das msiexec verwendet:

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"
2
RBT
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
                }
            }
        }
    }
}

Nenne es so:

Uninstall-App "Autodesk Revit DB Link 2019"
2
Ehsan Irannejad

Basierend auf Jeff Hillmans Antwort:

Hier ist eine Funktion, die Sie einfach zu Ihrem profile.ps1 Hinzufügen oder in der aktuellen PowerShell-Sitzung definieren können:

# 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 + "'")
    }
}

Angenommen, Sie wollten Notepad ++ deinstallieren. Geben Sie dies einfach in PowerShell ein:

> uninstall("notepad++")

Beachten Sie jedoch, dass Get-WmiObject Einige Zeit in Anspruch nehmen kann. Seien Sie also geduldig!

1
Kolob Canyon

Eine Codezeile:

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

Benutzen:

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}"

Es wurde nicht vollständig getestet, lief aber unter PowerShell 4.

Ich habe die PS1-Datei so ausgeführt, wie sie hier angezeigt wird. Lassen Sie alle Systeme von AD abrufen und versuchen, mehrere Anwendungen auf allen Systemen zu deinstallieren.

Ich habe die IdentifyingNumber verwendet, um nach der Software-Ursache für die Eingabe von David Stetlers zu suchen.

Nicht getestet:

  1. Dem Aufruf der Funktion im Skript keine IDs hinzufügen, sondern das Skript mit Parameter-IDs starten
  2. Aufruf des Skripts mit mehr als einem Computernamen not wird automatisch von der Funktion abgerufen
  3. Daten aus der Pipe abrufen
  4. Verwenden von IP-Adressen zur Verbindung mit dem System

Was es nicht tut:

  1. Es gibt keine Informationen darüber, ob die Software tatsächlich auf einem bestimmten System gefunden wurde.
  2. Es gibt keine Informationen über Fehler oder Erfolg der Deinstallation.

Ich konnte nicht deinstallieren (). Beim Versuch, dass ich eine Fehlermeldung erhalten habe, die besagt, dass das Aufrufen einer Methode für einen Ausdruck mit dem Wert NULL nicht möglich ist. Stattdessen habe ich Remove-WmiObject verwendet, was scheinbar dasselbe bewirkt.

ACHTUNG: Ohne einen Computernamen wird die Software von ALL -Systemen im Active Directory entfernt.

0
user3410872

Für die meisten meiner Programme haben die Skripte in diesem Post die Aufgabe erledigt ... Aber ich musste mich einem älteren Programm stellen, das ich mit der msiexec.exe- oder Win32_Product-Klasse nicht entfernen konnte. (aus irgendeinem Grund bekam ich Ausgang 0, aber das Programm war noch da)

Meine Lösung bestand darin, die Klasse Win32_Process zu verwenden:

mit der Hilfe von nickdnk Mit diesem Befehl erhalten Sie den Pfad zur Deinstallation der exe-Datei:

64bit:

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

32bit:

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

sie müssen die Ergebniszeichenfolge bereinigen:

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

wenn Sie nun den entsprechenden program-Deinstallationsdateipfad haben, können Sie diesen Befehl verwenden:

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

$ uninstallResult - enthält den Exit-Code. 0 ist Erfolg

die obigen Befehle können auch remote ausgeführt werden - ich habe es mit dem Befehl invoke ausgeführt, aber ich glaube, dass das Hinzufügen des Arguments -computername funktionieren kann

0
dsaydon