PowerShell kullanarak bir uygulamayı nasıl kaldırabilirim?


136

Varolan bir uygulamayı kaldırmak için PowerShell kullanarak standart ' Program Ekle veya Kaldır ' işlevselliğine bağlanmanın basit bir yolu var mı ? Veya uygulamanın yüklü olup olmadığını kontrol etmek için?

Yanıtlar:


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

$app.Uninstall()

Düzenleme: Rob bunu Filter parametresiyle yapmanın başka bir yolunu buldu:

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

1
Bu hemen hemen bu, her durumda, IdentifyingNumber kullanmanın daha iyi olabileceğini söyleyebilirim.
Küvetler

6
Biraz araştırma yaptıktan sonra Get-WmiObject'in -filter yan tümcesini de kullanabilirsiniz: $ app = Get-WmiObject -Class Win32_Product -filter "select * from Win32_Product WHERE name = 'Software Name'"
Rob Paterson

8
WMI'ya bakmanın yalnızca bir MSI aracılığıyla kurulan ürünler için çalışacağını unutmayın.
EBGreen

7
Bu WMI sınıfının numaralandırılması FOREVER alır. Jeff'e Rob'un ipucunu eklemek için kodunuzu güncellemenizi öneririm.
halr9000

4
(gwmi Win32_Product | ? Name -eq "Software").uninstall() Biraz kod golf.
roundar

51

DÜZENLEME: Yıllar içinde bu cevap oldukça az sayıda oy aldı. Bazı yorumlar eklemek istiyorum. O zamandan beri PowerShell'i kullanmadım, ancak bazı sorunları gözlemlediğimi hatırlıyorum:

  1. Aşağıdaki komut dosyası için 1'den fazla eşleşme varsa, çalışmaz ve sonuçları 1 ile sınırlayan PowerShell filtresini eklemeniz gerekir. -First 1 ama emin değilim. Düzenlemek için çekinmeyin.
  2. Uygulama MSI tarafından yüklenmezse, çalışmaz. Aşağıdaki gibi yazılmasının nedeni, MSI'yı müdahale etmeden kaldırılacak şekilde değiştirmesidir; bu, yerel kaldırma dizesini kullanırken her zaman varsayılan durum değildir.

WMI nesnesini kullanmak sonsuza kadar sürer. Kaldırmak istediğiniz programın adını biliyorsanız, bu çok hızlıdır.

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

1
Bunun için teşekkürler! -like "appNam*"Sürüm adında olduğu ve değiştiği için bu ile kullanmaya çalışıyorum , ama programı bulmak gibi görünmüyor. Herhangi bir fikir?
NSouth

1
Powershell için -like işlevine bakın, dizeyi doğru şekilde eşleştirmek için nasıl kullanılacak filtreyi bulun. Sadece test etmek için kabuğu kullanın ve bir kez doğru olsun
-match

2
Bu altın. Şahsen, 'b' yi '/ qb' den kaldırırım, böylece herhangi bir diyalog görmeniz gerekmez.
WhiteHotLoveTiger

Çok daha hızlı :-)
Oscar Foley

3
Bunu komut istemi olan bir .ps1 betiğine ve "kaldırmak üzere olduğum" bilgisine çevirdim. gist.github.com/chrisfcarroll/e38b9ffcc52fa9d4eb9ab73b13915f5a
Chris F Carroll

34

Jeff Hillman'ın gönderisindeki ikinci yöntemi düzeltmek için aşağıdakilerden birini yapabilirsiniz:

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

Veya

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

Sadece bir heads-up ... "-Filter" seçeneği yerine "-Query" kullanmanın bir WmiObject döndürmediğini, bu yüzden bir "uninstall" yöntemi olmadığını buldum.
Doug J. Huras

7

Win32_Product sınıfının onarımları tetiklediği ve sorgu için optimize edilmediği için önerilmediğini öğrendim. Kaynak

Ben app guid biliyorsanız kaldırmak için bir komut dosyası ile Sitaram Pamarthi bu yazı bulundu . Ayrıca burada uygulamaları çok hızlı aramak için başka bir komut dosyası da sağlıyor .

Bunun gibi kullanın:. \ 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"}
 }

7

Bu gönderiye biraz eklemek için, yazılımı birden çok Sunucudan kaldırabilmem gerekiyordu. Jeff'in cevabını beni buna yönlendirmek için kullandım:

İlk önce bir sunucu listesi aldım, bir AD sorgusu kullandım, ancak istediğiniz gibi bilgisayar adları dizisini sağlayabilirsiniz:

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

Sonra gwmi sorgusuna -computer parametresini ekleyerek, onların üzerinden döngü:

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

Doğru uygulamayı kaldırdığımdan emin olmak için name yerine eşleştirmek için IdentifyingNumber özelliğini kullandım.


Sadece güzel bu çözüm
Raffaeu

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

Bu şekilde arayın:

Uninstall-App "Autodesk Revit DB Link 2019"


3

Kendi küçük katkımı yapacağım. Paketlerin listesini aynı bilgisayardan kaldırmam gerekiyordu. Bu benim bulduğum senaryo.

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

Umarım bu yararlı olur.

David Stetler'e dayandığı için bu senaryo için kredi borcum olduğunu unutmayın.


2

Msiexec kullanan PowerShell betiği:

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"

Bu yaklaşımı aşağıdaki bayraklarla birleştirdim , nedense bu benim için diğer yaklaşımlardan daha iyi çalışıyor.
David Rogers

1

Jeff Hillman'ın cevabına dayanarak:

profile.ps1Geçerli PowerShell oturumunuza ekleyebileceğiniz veya tanımlayabileceğiniz bir işlev şunlardır:

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

Diyelim ki Notepad ++ yazılımını kaldırmak istiyorsunuz . Bunu PowerShell'e yazmanız yeterlidir:

> uninstall("notepad++")

Sadece Get-WmiObjectbiraz zaman alabileceğini unutmayın, bu yüzden sabırlı olun!


0

kullanın:

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

Tam olarak test edilmedi, ancak PowerShell 4 altında koştu.

PS1 dosyasını burada görüldüğü gibi çalıştırdım. AD'den tüm Sistemleri almasına izin vermek vermek ve tüm sistemlerde birden fazla uygulamayı kaldırmaya çalışmak.

David Stetlers girdisinin Yazılım nedenini aramak için IdentifyingNumber'ı kullandım.

Test edilmedi:

  1. Komut dosyasındaki işlevin çağrısına kimlik eklememek, komut dosyasını parametre kimlikleriyle başlatmak
  2. Komut dosyasını 1'den fazla bilgisayar adıyla çağırmamak otomatik fonksiyonu alınan
  3. Borudan veri alma
  4. Sisteme bağlanmak için IP adreslerini kullanma

Ne yapmaz:

  1. Yazılım gerçekten herhangi bir sistemde bulunursa herhangi bir bilgi vermez.
  2. Kaldırma işleminin başarısızlığı veya başarısı hakkında herhangi bir bilgi vermez.

Uninstall () yöntemini kullanamadım. NULL değeri olan bir ifade için bir yöntem çağırmanın mümkün olmadığını söyleyen bir hata aldım. Bunun yerine, aynı şeyi başarmış görünen Remove-WmiObject kullandım.

DİKKAT : Verilen bir bilgisayar adı olmadan, yazılımı Active Directory'deki TÜM sistemlerden kaldırır .


0

Programlarımın çoğu için bu Post'taki komut dosyaları işi yaptı. Ama msiexec.exe veya Win32_Product sınıfını kullanarak kaldıramadığım eski bir programla karşı karşıya kaldım. (bazı nedenlerden 0 çıkış aldım ama program hala oradaydı)

Benim çözüm Win32_Process sınıfı kullanmak oldu:

nickdnk yardımı ile bu komut kaldırma exe dosya yolunu elde etmektir:

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

sonuç dizesini temizlemeniz gerekir:

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

şimdi ilgili program kaldırma exe dosya yolu olduğunda bu komutu kullanabilirsiniz:

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

$ uninstallResult - çıkış koduna sahip olur. 0 başarıdır

Yukarıdaki komutlar da uzaktan çalışabilir - invoke komutunu kullanarak yaptım ama -computername değişkeninin eklenmesinin işe yarayabileceğine inanıyorum

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.