Como posso desinstalar um aplicativo usando o PowerShell?
-
02-07-2019 - |
Pergunta
Existe uma maneira simples de ligar para o padrão ' Adicionar ou remover programas ' funcionalidade usando PowerShell para desinstalar um aplicativo existente ? Ou para verificar se o aplicativo está instalado?
Solução
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "Software Name"
}
$app.Uninstall()
Editar: Rob encontrou outra maneira de fazê-lo com o parâmetro Filter:
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
Outras dicas
EDIT: Ao longo dos anos esta resposta tem obtido muito poucos upvotes. Eu gostaria de acrescentar alguns comentários. Eu não usei PowerShell uma vez, mas eu lembro de observar algumas questões:
- Se houver mais partidas do que 1 para o abaixo script, ele não funciona e você deve acrescentar o filtro PowerShell que limita os resultados para 1. Eu acredito que é
-First 1
mas eu não tenho certeza. Sinta-se livre para editar. - Se o aplicativo não é instalado por MSI ele não funciona. A razão foi escrito como abaixo é porque ele modifica a MSI a desinstalação sem intervenção, o que nem sempre é o caso padrão quando utilizando a cadeia de desinstalação nativa.
Usando o objeto WMI leva uma eternidade. Isto é muito rápido se você só sabe o nome do programa que você deseja 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 corrigir o segundo método no post de Jeff Hillman, você poderia fazer um:
$app = Get-WmiObject
-Query "SELECT * FROM Win32_Product WHERE Name = 'Software Name'"
ou
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
Para adicionar um pouco para este post, eu precisava ser capaz de remover o software de múltiplos servidores. Eu usei a resposta de Jeff para me levar a este:
Primeiro eu tenho uma lista de servidores, eu usei um AD consulta, mas você pode proporcionar a matriz de nomes de computador como quiser:
$computers = @("computer1", "computer2", "computer3")
Então eu loop através deles, adicionando o parâmetro -computer à 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()
}
Eu usei a propriedade IdentifyingNumber para o jogo contra vez de nome, só para ter certeza que eu estava desinstalar o aplicativo correto.
Eu descobri que a classe Win32_Product não é recomendado porque ele aciona reparos e não é consulta otimizada. Fonte
este post de Sitaram Pamarthi com um script para desinstalar se você sabe o guid aplicativo. Ele também fornece um outro script para procurar aplicativos muito rápido aqui .
Use como este:. \ 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
}
}
}
}
}
Chamá-lo desta maneira:
Uninstall-App "Autodesk Revit DB Link 2019"
Vou fazer a minha própria contribuição pequena. Eu precisava remover uma lista de pacotes a partir do mesmo computador. Este é o script que eu vim com.
$packages = @("package1", "package2", "package3")
foreach($package in $packages){
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "$package"
}
$app.Uninstall()
}
Espero que isso prova ser útil.
Note que devo David Stetler o crédito para esse script, uma vez que é baseado em seu.
Aqui está o PowerShell script 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"
Uma linha de código:
get-package *notepad* |% { & $_.Meta.Attributes["UninstallString"]}
Com base na resposta de Jeff Hillman:
Aqui está uma função que você pode simplesmente adicionar ao seu profile.ps1
ou definir na sessão atual 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 + "'")
}
}
Vamos dizer que você queria desinstalação Notepad ++ . Basta digitar isso em PowerShell:
> uninstall("notepad++")
Esteja ciente de que Get-WmiObject
pode levar algum tempo, então seja paciente!
Use:
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}"
Não é totalmente testado, mas ele correu sob PowerShell 4.
Eu executar o arquivo PS1 como é visto aqui. Deixá-lo recuperar todos os sistemas do AD e tentando desinstalar aplicações múltiplas em todos os sistemas.
Eu usei o IdentifyingNumber para procurar a causa Software de entrada de David Stetlers.
Não testado:
- Não acrescentando ids para a chamada da função no script, em vez de iniciar o script com o parâmetro IDs
- Chamando o script com mais de 1 Nome do computador não recuperado automaticamente a partir da função
- A recuperação de dados a partir do tubo
- Usando endereços IP para se conectar ao sistema
O que não faz:
- Não dá qualquer informação se o software realmente foi encontrado em um determinado sistema.
- Ele não dá qualquer informação sobre o fracasso ou o sucesso da desinstalação.
Eu não era capaz de usar a desinstalação (). Tentando que eu tenho um erro dizendo-me que chamar um método para uma expressão que tem um valor de NULL não é possível. Em vez disso eu usei Remove-WmiObject, que parece realizar a mesma.
ATENÇÃO :. Sem um nome de computador dado que remove o software de ALL sistemas do Active Directory
Para a maioria de meus programas os scripts neste post fez o trabalho. Mas eu tive que enfrentar um programa legado que eu não poderia remover usando msiexec.exe ou classe Win32_Product. (De alguma razão eu tenho exit 0, mas o programa ainda estava lá)
A minha solução foi usar classe Win32_Process:
com a ajuda de nickdnk este comando é obter o caminho do arquivo executável de desinstalação:
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
Você terá que limpar a seqüência de resultado:
$uninstallPath = $unInstallPathReg[0].UninstallString
$uninstallPath = $uninstallPath -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
$uninstallPath = $uninstallPath .Trim()
Agora, quando você tem a programa de desinstalação caminho do arquivo exe relevantes você pode usar este comando:
$uninstallResult = (Get-WMIObject -List -Verbose | Where-Object {$_.Name -eq "Win32_Process"}).InvokeMethod("Create","$unInstallPath")
$ uninstallResult - terá o código de saída. 0 é o sucesso
os comandos acima também pode executar remotamente - Eu fiz isso usando invocação de comando, mas eu acredito que adicionando o argumento -computername pode trabalhar