web-dev-qa-db-fra.com

Comment puis-je désinstaller une application à l'aide de PowerShell?

Existe-t-il un moyen simple de se connecter à la fonctionnalité standard 'Ajouter ou supprimer des programmes' à l'aide de PowerShell pour désinstaller une application existante? Ou pour vérifier si l'application est installée?

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

$app.Uninstall()

Edit: Rob a trouvé un autre moyen de le faire avec le paramètre Filter:

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

EDIT: Au fil des ans, cette réponse a reçu pas mal de votes positifs. Je voudrais ajouter quelques commentaires. Je n'ai pas utilisé PowerShell depuis, mais je me souviens avoir observé certains problèmes:

  1. S'il y a plus de correspondances que 1 pour le script ci-dessous, cela ne fonctionne pas et vous devez ajouter le filtre PowerShell qui limite les résultats à 1. Je crois que c'est -First 1 mais je ne suis pas sûr. N'hésitez pas à éditer.
  2. Si l'application n'est pas installée par MSI, cela ne fonctionne pas. La raison pour laquelle il a été écrit comme suit est qu’elle modifie le MSI pour désinstaller sans intervention, ce qui n’est pas toujours le cas par défaut lors de l’utilisation de la chaîne de désinstallation native.

L'utilisation de l'objet WMI prend une éternité. Ceci est très rapide si vous connaissez simplement le nom du programme que vous souhaitez désinstaller.

$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

Pour corriger la deuxième méthode dans le post de Jeff Hillman, vous pouvez soit faire un:

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

Ou

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

Pour ajouter un peu à ce post, je devais être capable de supprimer des logiciels de plusieurs serveurs. J'ai utilisé la réponse de Jeff pour me conduire à ceci:

J'ai d'abord eu une liste de serveurs, j'ai utilisé une requête AD , mais vous pouvez fournir le tableau de noms d'ordinateurs comme vous le souhaitez:

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

Puis je les ai parcourues en boucle, en ajoutant le paramètre -computer à la requête gwmi:

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

J'ai utilisé la propriété IdentifyingNumber pour rechercher une correspondance au lieu de nom, juste pour m'assurer de désinstaller l'application appropriée.

7
David Stetler

J'ai découvert que la classe Win32_Product n'est pas recommandée car elle déclenche des réparations et n'est pas optimisée pour les requêtes. La source

J'ai trouvé ce message de Sitaram Pamarthi avec un script à désinstaller si vous connaissez le guide d'application. Il fournit également un autre script pour rechercher des applications très rapidement ici .

Utilisez comme ceci:.\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

Je vais faire ma propre petite contribution. Je devais supprimer une liste de paquets du même ordinateur. Ceci est le script que je suis venu avec.

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

J'espère que cela s'avère utile.

Notez que je dois à David Stetler le mérite de ce script car il est basé sur le sien.

3
Ben Key

Voici le script PowerShell utilisant 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"
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
                }
            }
        }
    }
}

Appelez ça comme ça:

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

Une ligne de code:

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

Utilisation:

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

Ce n'est pas complètement testé, mais il fonctionnait sous PowerShell 4.

J'ai couru le fichier PS1 comme on le voit ici. Laissez-le récupérer tous les systèmes de AD et essayez de désinstaller plusieurs applications sur tous les systèmes.

J'ai utilisé IdentifyingNumber pour rechercher la cause logicielle de l'entrée de David Stetlers.

Pas testé:

  1. N'ajoutant pas d'identifiants à l'appel de la fonction dans le script, démarrant le script avec des identifiants de paramètres
  2. Appel du script avec plus d'un nom d'ordinateur pas automatiquement récupéré à partir de la fonction
  3. Récupérer des données du tuyau
  4. Utilisation d'adresses IP pour se connecter au système

Ce qu'il ne fait pas:

  1. Cela ne donne aucune information si le logiciel a été trouvé sur un système donné.
  2. Il ne donne aucune information sur l'échec ou le succès de la désinstallation.

Je n'ai pas pu utiliser uninstall (). Essayer d'obtenir une erreur me disant qu'appeler une méthode pour une expression ayant la valeur NULL n'est pas possible. Au lieu de cela, j'ai utilisé Remove-WmiObject, qui semble accomplir la même chose.

CAUTION: sans nom d'ordinateur, il supprime le logiciel de TOUS LES SYSTÈMES de l'Active Directory.

0
user3410872

Pour la plupart de mes programmes, les scripts de cette publication ont fait le travail… .. Mais j'ai dû faire face à un programme existant que je ne pouvais pas supprimer à l'aide de la classe msiexec.exe ou Win32_Product. (pour une raison quelconque, j'ai eu la sortie 0 mais le programme était toujours là)

Ma solution consistait à utiliser la classe Win32_Process:

avec l'aide de nickdnk cette commande consiste à obtenir le chemin du fichier de désinstallation exe:

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

vous devrez nettoyer la chaîne de résultat:

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

maintenant, lorsque vous avez le chemin de fichier exe correspondant au programme de désinstallation programme, vous pouvez utiliser cette commande:

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

$ uninstallResult - aura le code de sortie. 0 est le succès

les commandes ci-dessus peuvent aussi fonctionner à distance - je l'ai fait en utilisant la commande invoke mais je pense que l'ajout de l'argument -computername peut fonctionner

0
dsaydon