ฉันจะถอนการติดตั้งแอปพลิเคชันโดยใช้ PowerShell ได้อย่างไร


136

มีวิธีง่ายๆในการเชื่อมต่อกับฟังก์ชัน' เพิ่มหรือลบโปรแกรม ' มาตรฐานโดยใช้ PowerShell เพื่อถอนการติดตั้งแอปพลิเคชันที่มีอยู่หรือไม่? หรือเพื่อตรวจสอบว่ามีการติดตั้งแอปพลิเคชันหรือไม่?

คำตอบ:


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

$app.Uninstall()

แก้ไข: Rob พบวิธีอื่นในการดำเนินการกับพารามิเตอร์ตัวกรอง:

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

1
นี่เป็นสิ่งที่ดีมากฉันจะบอกว่ามันอาจจะดีกว่าถ้าใช้ IdentifyingNumber แทนที่จะใช้ชื่อในกรณี
อ่าง

6
หลังจากการวิจัยเล็กน้อยคุณยังสามารถใช้ -filter clause ของ Get-WmiObject: $ app = Get-WmiObject -Class Win32_Product -filter "select * from Win32_Product WHERE name = 'Software Name'"
Rob Paterson

8
โปรดทราบว่าการดู WMI จะใช้ได้กับผลิตภัณฑ์ที่ติดตั้งผ่าน MSI เท่านั้น
EBGreen

7
คลาส WMI นี้ใช้ FOREVER เพื่อแจกแจง ฉันขอแนะนำให้เจฟฟ์อัปเดตโค้ดของคุณเพื่อรวมเคล็ดลับของร็อบ
halr9000

5
(gwmi Win32_Product | ? Name -eq "Software").uninstall() กอล์ฟรหัสเล็กน้อย
รอบ

51

แก้ไข: ในช่วงหลายปีที่ผ่านมาคำตอบนี้ได้รับการโหวตเพิ่มขึ้นเล็กน้อย ผมอยากจะเพิ่มความคิดเห็น ฉันไม่ได้ใช้ PowerShell ตั้งแต่นั้นมา แต่ฉันจำได้ว่าสังเกตปัญหาบางอย่าง:

  1. หากมีการจับคู่มากกว่า 1 รายการสำหรับสคริปต์ด้านล่างจะไม่ทำงานและคุณต้องต่อท้ายตัวกรอง PowerShell ที่ จำกัด ผลลัพธ์เป็น 1 ฉันเชื่อว่าเป็น-First 1แต่ฉันไม่แน่ใจ แก้ไขได้ตามต้องการ
  2. หาก MSI ไม่ได้ติดตั้งแอปพลิเคชันนั้นจะไม่ทำงาน สาเหตุที่เขียนไว้ด้านล่างนี้เป็นเพราะมันปรับเปลี่ยน MSI ให้ถอนการติดตั้งโดยไม่มีการแทรกแซงซึ่งไม่ใช่กรณีเริ่มต้นเสมอไปเมื่อใช้สตริงการถอนการติดตั้งดั้งเดิม

การใช้วัตถุ WMI ใช้เวลาตลอดไป นี่จะเร็วมากถ้าคุณรู้แค่ชื่อโปรแกรมที่คุณต้องการถอนการติดตั้ง

$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
ขอบคุณสำหรับสิ่งนี้! ฉันกำลังพยายามใช้สิ่งนี้-like "appNam*"เนื่องจากเวอร์ชันอยู่ในชื่อและมีการเปลี่ยนแปลง แต่ดูเหมือนจะไม่พบโปรแกรม ความคิดใด ๆ ?
NSouth

1
ค้นหาฟังก์ชั่น -like สำหรับ powershell ค้นหาว่าตัวกรองใดที่จะใช้วิธีทำให้ตรงกับสตริงของคุณอย่างถูกต้อง เพียงแค่ใช้เปลือกเพื่อทดสอบและเมื่อคุณทำถูกต้องแล้วให้แทนที่
-match

2
นี่คือทองคำ ส่วนตัวฉันลบ 'b' ออกจาก '/ qb' ดังนั้นคุณจึงไม่ต้องเห็นกล่องโต้ตอบใด ๆ
WhiteHotLoveTiger

เร็วกว่ามาก :-)
Oscar Foley

4
ฉันเปลี่ยนสิ่งนี้เป็นสคริปต์. psd พร้อมข้อความแจ้งและข้อมูล "สิ่งที่ฉันกำลังจะถอนการติดตั้ง" gist.github.com/chrisfcarroll/e38b9ffcc52fa9d4eb9ab73b13915f5a
Chris F Carroll

34

ในการแก้ไขวิธีที่สองในโพสต์ของ Jeff Hillman คุณสามารถทำได้:

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

หรือ

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

โปรดทราบ ... ฉันพบว่าการใช้ "-Query" แทนตัวเลือก "-Filter" ไม่ได้ส่งคืน WmiObject ดังนั้นจึงไม่มีวิธี "ถอนการติดตั้ง"
Doug J.Huras

7

ฉันพบว่าไม่แนะนำให้ใช้คลาส Win32_Product เนื่องจากทริกเกอร์การซ่อมแซมและไม่ได้รับการเพิ่มประสิทธิภาพการสืบค้น ที่มา

ฉันพบโพสต์นี้จาก Sitaram Pamarthi พร้อมสคริปต์สำหรับถอนการติดตั้งหากคุณรู้คู่มือแอป นอกจากนี้เขายังซัพพลายสคริปต์อื่นเพื่อค้นหาปพลิเคชันได้อย่างรวดเร็วจริงๆที่นี่

ใช้ดังนี้:. \ 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

หากต้องการเพิ่มเล็กน้อยในโพสต์นี้ฉันต้องสามารถลบซอฟต์แวร์ออกจากเซิร์ฟเวอร์หลายตัวได้ ฉันใช้คำตอบของเจฟฟ์เพื่อนำฉันไปสู่สิ่งนี้:

ก่อนอื่นฉันมีรายชื่อเซิร์ฟเวอร์ฉันใช้แบบสอบถามADแต่คุณสามารถระบุอาร์เรย์ของชื่อคอมพิวเตอร์ได้ตามที่คุณต้องการ:

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

จากนั้นฉันก็วนซ้ำพวกเขาเพิ่มพารามิเตอร์ -computer ในแบบสอบถาม gwmi:

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

ฉันใช้คุณสมบัติ IdentifyingNumber เพื่อจับคู่แทนชื่อเพื่อให้แน่ใจว่าฉันกำลังถอนการติดตั้งแอปพลิเคชันที่ถูกต้อง


วิธีแก้ปัญหานี้น่ารักเพียง
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
                }
            }
        }
    }
}

เรียกวิธีนี้ว่า

Uninstall-App "Autodesk Revit DB Link 2019"


3

ฉันจะทำผลงานเล็ก ๆ น้อย ๆ ของตัวเอง ฉันต้องการลบรายการแพ็คเกจออกจากคอมพิวเตอร์เครื่องเดียวกัน นี่คือสคริปต์ที่ฉันคิดขึ้นมา

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

ฉันหวังว่านี่จะเป็นประโยชน์

โปรดทราบว่าฉันเป็นหนี้ David Stetler เครดิตสำหรับสคริปต์นี้เนื่องจากเป็นไปตามไฟล์.


2

นี่คือสคริปต์ PowerShell โดยใช้ 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"

ฉันรวมแนวทางนี้เข้ากับแฟล็กต่อไปนี้ด้วยเหตุผลบางประการวิธีนี้ได้ผลดีกว่าวิธีอื่น ๆ สำหรับฉัน
David Rogers

1

จากคำตอบของ Jeff Hillman:

นี่คือฟังก์ชันที่คุณสามารถเพิ่มprofile.ps1หรือกำหนดในเซสชัน 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 + "'")
    }
}

สมมติว่าคุณต้องการที่จะถอนการติดตั้งNotepad ++ เพียงพิมพ์สิ่งนี้ลงใน PowerShell:

> uninstall("notepad++")

เพียงแค่ทราบว่าGet-WmiObjectอาจใช้เวลาพอสมควรดังนั้นโปรดอดใจรอ!


0

ใช้:

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

ยังไม่ได้รับการทดสอบอย่างสมบูรณ์ แต่ทำงานภายใต้ PowerShell 4

ฉันเรียกใช้ไฟล์ PS1 ตามที่เห็นที่นี่ ปล่อยให้มันดึงระบบทั้งหมดจากADและพยายามถอนการติดตั้งหลายแอพพลิเคชั่นในทุกระบบ

ฉันใช้ IdentifyingNumber เพื่อค้นหาสาเหตุซอฟต์แวร์ของอินพุต David Stetlers

ไม่ผ่านการทดสอบ:

  1. ไม่เพิ่มรหัสในการเรียกใช้ฟังก์ชันในสคริปต์แทนที่จะเริ่มสคริปต์ด้วย ID พารามิเตอร์
  2. การเรียกใช้สคริปต์ด้วยชื่อคอมพิวเตอร์มากกว่า 1 ชื่อจะไม่ถูกเรียกจากฟังก์ชันโดยอัตโนมัติ
  3. กำลังดึงข้อมูลจากท่อ
  4. ใช้ที่อยู่ IP เพื่อเชื่อมต่อกับระบบ

สิ่งที่ไม่:

  1. จะไม่ให้ข้อมูลใด ๆ หากพบซอฟต์แวร์จริงในระบบใด ๆ
  2. ไม่ได้ให้ข้อมูลใด ๆ เกี่ยวกับความล้มเหลวหรือความสำเร็จของการถอนการติดตั้ง

ฉันไม่สามารถใช้การถอนการติดตั้ง () การพยายามทำให้ฉันได้รับข้อผิดพลาดที่บอกฉันว่าไม่สามารถเรียกเมธอดสำหรับนิพจน์ที่มีค่าเป็น NULL ได้ ฉันใช้ Remove-WmiObject แทนซึ่งดูเหมือนจะสำเร็จเหมือนกัน

ข้อควรระวัง : หากไม่มีชื่อคอมพิวเตอร์จะลบซอฟต์แวร์ออกจากระบบทั้งหมดใน Active Directory


0

สำหรับโปรแกรมส่วนใหญ่ของฉันสคริปต์ในโพสต์นี้ทำงานได้ดี แต่ฉันต้องเผชิญกับโปรแกรมดั้งเดิมที่ฉันไม่สามารถลบโดยใช้คลาส msiexec.exe หรือ Win32_Product (จากเหตุผลบางอย่างฉันได้ออกจาก 0 แต่โปรแกรมยังอยู่ที่นั่น)

วิธีแก้ปัญหาของฉันคือใช้คลาส Win32_Process:

ด้วยความช่วยเหลือจากnickdnkคำสั่งนี้คือการรับพา ธ ไฟล์ถอนการติดตั้ง exe:

64 บิต:

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

32 บิต:

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

คุณจะต้องล้างสตริงผลลัพธ์:

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

ตอนนี้เมื่อคุณมีพา ธ ไฟล์ exe ถอนการติดตั้งโปรแกรมที่เกี่ยวข้องคุณสามารถใช้คำสั่งนี้:

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

$ uninstallResult - จะมีรหัสออก 0 คือความสำเร็จ

คำสั่งข้างต้นยังสามารถเรียกใช้จากระยะไกลได้ - ฉันทำโดยใช้คำสั่งเรียกใช้ แต่ฉันเชื่อว่าการเพิ่มอาร์กิวเมนต์ - ชื่อคอมพิวเตอร์สามารถทำงานได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.