Як я можу видалити програму за допомогою PowerShell?


136

Чи є простий спосіб приєднатись до стандартної функції " Додати або видалити програми " за допомогою PowerShell для видалення наявної програми ? Або перевірити, чи встановлено додаток?

Відповіді:


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

$app.Uninstall()

Редагувати: Роб знайшов інший спосіб зробити це за допомогою параметра Filter:

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

1
Це в значній мірі, я б сказав, що може бути краще використовувати IdentifyingNumber, а не ім'я, на всякий випадок.
Ванна

6
Після невеликих досліджень ви також можете скористатись пунктом -filter Get-WmiObject: $ app = Get-WmiObject -Class Win32_Product -filter "select * from Win32_Product WHERE name = 'Ім'я програмного забезпечення" "
Роб Патерсон

8
Зауважте, що перегляд WMI працюватиме лише для продуктів, які були встановлені через MSI.
EBGreen

7
Цей клас WMI потребує FOREVER для перерахунку. Я пропоную Джеффу оновити свій код, щоб включити підказку Роба.
halr9000

4
(gwmi Win32_Product | ? Name -eq "Software").uninstall() Невеликий код гольфу.
округлий

51

EDIT: За ці роки ця відповідь отримала досить багато відгуків. Я хотів би додати кілька коментарів. З тих пір я не використовував 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*"оскільки версія входить до назви і вона змінюється, але, схоже, програма не знаходить. Будь-які ідеї?
південь

1
Знайдіть функцію -like для powershell, з’ясуйте, який фільтр використовувати, як правильно зрівняти ваш рядок. Просто використовуйте оболонку для тестування, і як тільки ви правильно це заміните -match :)
nickdnk

2
Це золото. Особисто я видаляю 'b' з '/ qb', тому вам не доведеться бачити діалоги.
WhiteHotLoveTiger

Набагато швидше :-)
Оскар Фолі

3
Я перетворив це на .ps1-скрипт із підказкою та інформацією про "що я збираюся видалити". gist.github.com/chrisfcarroll/e38b9ffcc52fa9d4eb9ab73b13915f5a
Chris F Carroll

34

Щоб виправити другий метод на посаді Джеффа Хілмана, ви можете зробити:

$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, тому у нього не було методу "видалення".
Дуг Дж. Гурас

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, щоб відповідати замість імені, просто щоб переконатися, що я видалив правильну програму.


Просто чудове це рішення
Раффау

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()
}

Я сподіваюся, що це виявляється корисним.

Зауважте, що я завдячую Девіду Стетлеру за заслуги за цей сценарій, оскільки він заснований на його.


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"

Я поєднав цей підхід із наступними прапорами , чомусь це працює краще, ніж інші підходи для мене.
Девід Роджерс

1

Спираючись на відповідь Джеффа Гілмена:

Ось функція, яку ви можете просто додати до свого 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, щоб шукати причину програмного забезпечення введення Девіда Стетлерса.

Не перевірено:

  1. Не додаючи ідентифікатори до виклику функції в скрипті, замість цього запустивши скрипт з ідентифікаторами параметра
  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 - успіх

вищезазначені команди також можна запускати віддалено - я робив це за допомогою команди invoke, але я вважаю, що додавання аргументу -іменник може працювати

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.