Bagaimana cara menghapus aplikasi menggunakan PowerShell?

136

Apakah ada cara sederhana untuk menghubungkan ke fungsionalitas ' Tambah atau Hapus Program ' standar menggunakan PowerShell untuk menghapus instalasi aplikasi yang ada ? Atau untuk memeriksa apakah aplikasi sudah diinstal?

Rob Paterson
sumber

Jawaban:

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

$app.Uninstall()

Edit: Rob menemukan cara lain untuk melakukannya dengan parameter Filter:

$app = Get-WmiObject -Class Win32_Product `
                     -Filter "Name = 'Software Name'"
Jeff Hillman
sumber
1
Ini cukup banyak, saya akan mengatakan bahwa mungkin lebih baik menggunakan IdentifyingNumber daripada namanya, untuk berjaga-jaga.
Bak mandi
6
Setelah sedikit riset, Anda juga dapat menggunakan -filter klausul Get-WmiObject: $ app = Get-WmiObject -Class Win32_Product -filter "pilih * dari Win32_Product WHERE name = 'Software Name'"
Rob Paterson
8
Perhatikan bahwa melihat WMI hanya akan berfungsi untuk produk yang diinstal melalui MSI.
EBGreen
7
Kelas WMI ini membutuhkan SELAMANYA untuk menghitung. Saya menyarankan Jeff agar Anda memperbarui kode Anda untuk menyertakan tip Rob.
halr9000
5
(gwmi Win32_Product | ? Name -eq "Software").uninstall() Sedikit kode golf.
Roundar
51

EDIT: Selama bertahun-tahun, jawaban ini mendapatkan cukup banyak suara positif. Saya ingin menambahkan beberapa komentar. Saya belum menggunakan PowerShell sejak itu, tetapi saya ingat mengamati beberapa masalah:

  1. Jika ada lebih dari 1 kecocokan untuk skrip di bawah ini, itu tidak berfungsi dan Anda harus menambahkan filter PowerShell yang membatasi hasil ke 1. Saya percaya itu -First 1tapi saya tidak yakin. Jangan ragu untuk mengedit.
  2. Jika aplikasi tidak diinstal oleh MSI, itu tidak berfungsi. Alasan penulisannya seperti di bawah ini adalah karena ia memodifikasi MSI untuk mencopot tanpa intervensi, yang tidak selalu merupakan kasus default saat menggunakan string pencopotan asli.

Menggunakan objek WMI membutuhkan waktu lama. Ini sangat cepat jika Anda hanya mengetahui nama program yang ingin Anda hapus instalannya.

$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}
nickdnk
sumber
1
Terima kasih untuk ini! Saya mencoba menggunakan ini dengan -like "appNam*"karena versinya ada di nama dan berubah, tetapi tampaknya tidak menemukan programnya. Ada ide?
NSouth
1
Cari fungsi -like untuk PowerShell, cari tahu filter mana yang digunakan dan bagaimana membuatnya cocok dengan string Anda dengan benar. Cukup gunakan shell untuk menguji, dan setelah Anda melakukannya dengan benar, ganti -match :)
nickdnk
2
Ini emas. Secara pribadi, saya menghapus 'b' dari '/ qb' sehingga Anda tidak perlu melihat dialog apa pun.
WhiteHotLoveTiger
Jauh lebih cepat :-)
Oscar Foley
4
Saya mengubahnya menjadi skrip .ps1 dengan prompt dan info "apa yang akan saya copot pemasangannya". gist.github.com/chrisfcarroll/e38b9ffcc52fa9d4eb9ab73b13915f5a
Chris F Carroll
34

Untuk memperbaiki metode kedua di postingan Jeff Hillman, Anda dapat melakukan:

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

Atau

$app = Get-WmiObject -Class Win32_Product `
                     -Filter "Name = 'Software Name'"
Robert Wagner
sumber
Sekadar pemberitahuan ... Saya menemukan bahwa menggunakan "-Query" daripada opsi "-Filter" tidak mengembalikan WmiObject, jadi tidak ada metode "uninstall".
Doug J. Huras
7

Saya menemukan bahwa kelas Win32_Product tidak disarankan karena memicu perbaikan dan tidak dioptimalkan kueri. Sumber

saya menemukan posting ini dari Sitaram Pamarthi dengan skrip untuk dihapus jika Anda tahu pedoman aplikasi. Dia juga menyediakan skrip lain untuk mencari aplikasi dengan sangat cepat di sini .

Gunakan seperti ini:. \ 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"}
 }
Ricardo
sumber
7

Untuk menambahkan sedikit ke posting ini, saya harus dapat menghapus perangkat lunak dari beberapa Server. Saya menggunakan jawaban Jeff untuk mengarahkan saya ke ini:

Pertama saya mendapat daftar server, saya menggunakan kueri AD , tetapi Anda dapat memberikan larik nama komputer sesuka Anda:

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

Kemudian saya mengulanginya, menambahkan parameter -komputer ke kueri gwmi:

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

Saya menggunakan properti IdentifyingNumber untuk dicocokkan dengan alih-alih nama, hanya untuk memastikan saya mencopot pemasangan aplikasi yang benar.

David Stetler
sumber
Cukup indah solusi ini
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
                }
            }
        }
    }
}

Sebut saja begini:

Uninstall-App "Autodesk Revit DB Link 2019"
Ehsan Iran-Nejad
sumber
6

Satu baris kode:

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

Saya akan memberikan kontribusi kecil saya sendiri. Saya perlu menghapus daftar paket dari komputer yang sama. Ini adalah skrip yang saya buat.

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

Saya harap ini terbukti bermanfaat.

Perhatikan bahwa saya berutang kredit kepada David Stetler untuk skrip ini karena skrip ini didasarkan padanya.

Ben Key
sumber
2

Berikut ini skrip PowerShell menggunakan 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"
NSP
sumber
Saya menggabungkan pendekatan ini dengan tanda berikut , untuk beberapa alasan ini bekerja lebih baik daripada pendekatan lain untuk saya.
David Rogers
1

Berdasarkan jawaban Jeff Hillman:

Berikut adalah fungsi yang bisa Anda tambahkan profile.ps1atau tentukan di sesi PowerShell saat ini:

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

Katakanlah Anda ingin menghapus Notepad ++ . Ketik saja ini ke PowerShell:

> uninstall("notepad++")

Sadarilah bahwa itu Get-WmiObjectbisa memakan waktu, jadi bersabarlah!

Ngarai Kolob
sumber
0

Menggunakan:

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

Ini belum sepenuhnya diuji, tetapi berjalan di bawah PowerShell 4.

Saya telah menjalankan file PS1 seperti yang terlihat di sini. Membiarkannya mengambil semua Sistem dari AD dan mencoba menghapus beberapa aplikasi di semua sistem.

Saya telah menggunakan IdentifyingNumber untuk mencari penyebab Software masukan David Stetlers.

Tidak diuji:

  1. Tidak menambahkan id ke pemanggilan fungsi dalam skrip, melainkan memulai skrip dengan ID parameter
  2. Memanggil skrip dengan lebih dari 1 nama komputer tidak secara otomatis diambil dari fungsi
  3. Mengambil data dari pipa
  4. Menggunakan alamat IP untuk terhubung ke sistem

Apa yang tidak:

  1. Itu tidak memberikan informasi apa pun jika perangkat lunak benar-benar ditemukan pada sistem tertentu.
  2. Itu tidak memberikan informasi apa pun tentang kegagalan atau keberhasilan penghapusan instalasi.

Saya tidak dapat menggunakan uninstall (). Mencoba bahwa saya mendapat kesalahan yang memberi tahu saya bahwa memanggil metode untuk ekspresi yang memiliki nilai NULL tidak mungkin. Sebaliknya saya menggunakan Hapus-WmiObject, yang tampaknya mencapai hal yang sama.

PERHATIAN : Tanpa nama komputer yang diberikan, itu menghapus perangkat lunak dari SEMUA sistem di Active Directory.

pengguna3410872
sumber
0

Untuk Sebagian besar program saya, skrip dalam Posting ini melakukan pekerjaan itu. Tetapi saya harus menghadapi program warisan yang tidak dapat saya hapus menggunakan kelas msiexec.exe atau Win32_Product. (dari beberapa alasan saya keluar 0 tapi program itu masih ada)

Solusi saya adalah menggunakan kelas Win32_Process:

dengan bantuan dari nickdnk perintah ini adalah untuk mendapatkan path file exe uninstall:

64 bit:

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

32 bit:

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

Anda harus membersihkan string hasil:

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

sekarang ketika Anda memiliki program yang relevan uninstall jalur file exe Anda dapat menggunakan perintah ini:

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

$ uninstallResult - akan memiliki kode keluar. 0 adalah sukses

perintah di atas juga dapat berjalan dari jarak jauh - saya melakukannya menggunakan perintah pemanggilan tetapi saya yakin bahwa menambahkan argumen-nama komputer dapat berfungsi

dsaydon
sumber