Làm cách nào để gỡ cài đặt ứng dụng bằng PowerShell?


136

Có cách nào đơn giản để nối vào chức năng ' Thêm hoặc xóa chương trình ' tiêu chuẩn bằng PowerShell để gỡ cài đặt ứng dụng hiện có không? Hoặc để kiểm tra nếu ứng dụng được cài đặt?

Câu trả lời:


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

$app.Uninstall()

Chỉnh sửa: Rob tìm thấy một cách khác để làm điều đó với tham số Bộ lọc:

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

1
Điều này là khá nhiều, tôi sẽ nói rằng nó có thể tốt hơn để sử dụng IdentifyingNumber thay vì tên, chỉ trong trường hợp.
Bồn tắm

6
Sau khi nghiên cứu một chút, bạn cũng có thể sử dụng mệnh đề -filter của Get-WmiObject: $ app = Get-WmiObject -Class Win32_ Productt -filter "select * từ Win32_Sản phẩm WHERE name = 'Tên phần mềm'"
Rob Paterson

8
Lưu ý rằng việc xem WMI sẽ chỉ hoạt động đối với các sản phẩm được cài đặt thông qua MSI.
EBGreen

7
Lớp WMI này mất FOREVER để liệt kê. Tôi đề nghị Jeff rằng bạn cập nhật mã của mình để bao gồm mẹo của Rob.
halr9000

4
(gwmi Win32_Product | ? Name -eq "Software").uninstall() Một ít mã golf.
vòng

51

EDIT: Trong những năm qua, câu trả lời này đã nhận được khá nhiều sự ủng hộ. Tôi muốn thêm một số ý kiến. Tôi chưa sử dụng PowerShell, nhưng tôi nhớ quan sát một số vấn đề:

  1. Nếu có nhiều kết quả khớp hơn 1 cho tập lệnh bên dưới, nó không hoạt động và bạn phải nối thêm bộ lọc PowerShell giới hạn kết quả thành 1. Tôi tin là -First 1vậy nhưng tôi không chắc. Hãy chỉnh sửa.
  2. Nếu ứng dụng không được MSI cài đặt thì nó không hoạt động. Lý do nó được viết như dưới đây là vì nó sửa đổi MSI để gỡ cài đặt mà không cần can thiệp, đây không phải là trường hợp mặc định khi sử dụng chuỗi gỡ cài đặt gốc.

Sử dụng đối tượng WMI sẽ mất mãi mãi. Điều này rất nhanh nếu bạn chỉ biết tên chương trình bạn muốn gỡ cài đặt.

$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
Cảm ơn vì điều đó! Tôi đang cố gắng sử dụng cái này -like "appNam*"vì phiên bản có tên và nó thay đổi, nhưng dường như nó không tìm thấy chương trình. Có ý kiến ​​gì không?
NSouth

1
Tra cứu hàm giống như cho powershell, tìm ra bộ lọc nào sẽ sử dụng cách làm cho nó khớp với chuỗi của bạn một cách chính xác. Chỉ cần sử dụng shell để kiểm tra và khi bạn nhận được nó, hãy thay thế -match :)
nickdnk 16/1/2015

2
Đây là vàng. Cá nhân, tôi xóa 'b' khỏi '/ qb' để bạn không phải xem bất kỳ hộp thoại nào.
WhiteHotLoveTiger

Nhanh hơn nhiều :-)
Oscar Foley

3
Tôi đã biến tập lệnh này thành tập lệnh .ps1 với lời nhắc và thông tin "những gì tôi sắp gỡ cài đặt". gist.github.com/chrisfcarroll/e38b9ffcc52fa9d4eb9ab73b13915f5a
Chris F Carroll

34

Để sửa phương thức thứ hai trong bài của Jeff Hillman, bạn có thể thực hiện:

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

Hoặc là

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

Chỉ cần một cái đầu ... Tôi thấy rằng việc sử dụng tùy chọn "-Query" thay vì tùy chọn "-Filter" không trả về WmiObject, vì vậy nó không có phương thức "gỡ cài đặt".
Doug J. Huras

7

Tôi phát hiện ra rằng lớp Win32_ Productt không được khuyến nghị vì nó kích hoạt sửa chữa và không được tối ưu hóa truy vấn. Nguồn

Tôi tìm thấy bài đăng này từ Sitaram Pamarthi với một đoạn script để gỡ cài đặt nếu bạn biết hướng dẫn ứng dụng. Ông cũng cung cấp một kịch bản khác để tìm kiếm các ứng dụng thực sự nhanh chóng ở đây .

Sử dụng như thế này :. \ 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

Để thêm một chút vào bài đăng này, tôi cần có khả năng xóa phần mềm khỏi nhiều Máy chủ. Tôi đã sử dụng câu trả lời của Jeff để dẫn tôi đến điều này:

Đầu tiên tôi có một danh sách các máy chủ, tôi đã sử dụng truy vấn AD , nhưng bạn có thể cung cấp mảng tên máy tính theo cách bạn muốn:

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

Sau đó, tôi lặp qua chúng, thêm tham số -computer vào truy vấn gwmi:

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

Tôi đã sử dụng thuộc tính IdentifyingNumber để khớp với thay vì tên, chỉ để chắc chắn rằng tôi đang gỡ cài đặt ứng dụng chính xác.


Chỉ đơn giản là đáng yêu giải pháp này
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
                }
            }
        }
    }
}

Gọi nó theo cách này:

Uninstall-App "Autodesk Revit DB Link 2019"


3

Tôi sẽ đóng góp nhỏ của riêng tôi. Tôi cần phải xóa một danh sách các gói từ cùng một máy tính. Đây là kịch bản tôi nghĩ ra.

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

Tôi hy vọng điều này chứng tỏ là hữu ích.

Lưu ý rằng tôi nợ David Stetler tín dụng cho kịch bản này vì nó dựa trên kịch bản của anh ấy.


2

Đây là tập lệnh PowerShell sử dụng 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"

Tôi đã kết hợp cách tiếp cận này với các cờ sau , vì một số lý do, cách này hiệu quả hơn các cách tiếp cận khác đối với tôi.
David Rogers

1

Dựa trên câu trả lời của Jeff Hillman:

Đây là một chức năng bạn chỉ có thể thêm vào profile.ps1hoặc xác định trong phiên PowerShell hiện tại:

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

Giả sử bạn muốn gỡ cài đặt Notepad ++ . Chỉ cần nhập cái này vào PowerShell:

> uninstall("notepad++")

Chỉ cần lưu ý rằng Get-WmiObjectcó thể mất một thời gian, vì vậy hãy kiên nhẫn!


0

Sử dụng:

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ó chưa được thử nghiệm đầy đủ, nhưng nó chạy dưới PowerShell 4.

Tôi đã chạy tệp PS1 như được thấy ở đây. Để nó truy xuất tất cả các Hệ thống từ AD và cố gắng gỡ cài đặt nhiều ứng dụng trên tất cả các hệ thống.

Tôi đã sử dụng Mã xác định để tìm kiếm nguyên nhân Phần mềm của đầu vào David Stetlers.

Không được kiểm tra:

  1. Không thêm id vào lệnh gọi của hàm trong tập lệnh, thay vào đó bắt đầu tập lệnh bằng ID tham số
  2. Gọi tập lệnh có nhiều hơn 1 tên máy tính không được tự động truy xuất từ ​​chức năng
  3. Lấy dữ liệu từ đường ống
  4. Sử dụng địa chỉ IP để kết nối với hệ thống

Những gì nó không:

  1. Nó không cung cấp bất kỳ thông tin nào nếu phần mềm thực sự được tìm thấy trên bất kỳ hệ thống nào.
  2. Nó không cung cấp bất kỳ thông tin nào về sự thất bại hoặc thành công của việc gỡ cài đặt.

Tôi không thể sử dụng gỡ cài đặt (). Cố gắng rằng tôi đã gặp lỗi khi nói với tôi rằng việc gọi một phương thức cho một biểu thức có giá trị NULL là không thể. Thay vào đó, tôi đã sử dụng Remove-WmiObject, có vẻ như hoàn thành tương tự.

THẬN TRỌNG : Không có tên máy tính được cung cấp, nó sẽ xóa phần mềm khỏi TẤT CẢ các hệ thống trong Active Directory.


0

Đối với hầu hết các chương trình của tôi, các kịch bản trong Bài đăng này đã thực hiện công việc. Nhưng tôi đã phải đối mặt với một chương trình cũ mà tôi không thể xóa bằng lớp msiexec.exe hoặc Win32_ Productt. (từ một số lý do tôi đã thoát 0 nhưng chương trình vẫn ở đó)

Giải pháp của tôi là sử dụng lớp Win32_Process:

với sự trợ giúp từ nickdnk , lệnh này là để lấy đường dẫn tệp exe gỡ cài đặt:

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

bạn sẽ phải xóa chuỗi kết quả:

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

Bây giờ khi bạn có chương trình liên quan gỡ cài đặt đường dẫn tệp exe, bạn có thể sử dụng lệnh này:

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

$ UninstallResult - sẽ có mã thoát. 0 là thành công

các lệnh trên cũng có thể chạy từ xa - Tôi đã thực hiện bằng lệnh invoke nhưng tôi tin rằng việc thêm đối số -computername có thể hoạt động

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.