Как удалить приложение с помощью PowerShell?


есть ли простой способ подключиться к стандарту'установка и удаление программ' функциональность с помощью PowerShell для удалить существующее приложение? Или проверить, установлено ли приложение?

10 107

10 ответов:

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

$app.Uninstall()

Edit: Роб нашел другой способ сделать это с параметром Filter:

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

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}

чтобы исправить второй метод в сообщении Джеффа Хиллмана, вы можете либо сделать:

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

или

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

чтобы добавить немного к этому сообщению, мне нужно было удалить программное обеспечение с нескольких серверов. Я использовал ответ Джеффа, чтобы привести меня к этому:

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

я узнал, что класс Win32_Product не рекомендуется, потому что он запускает ремонт и не оптимизирован для запросов. источник

нашел этот пост от Sitaram Pamarthi со скриптом для удаления, если вы знаете приложение guid. Он также поставляет другой скрипт для поиска приложений очень быстро здесь.

использовать следующим образом:. \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"}
 }

Я сделаю свой маленький вклад. Мне нужно было удалить список пакетов с того же компьютера. Это сценарий, который я придумал.

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

Я надеюсь, что это окажется полезным.

обратите внимание, что я должен Дэвид Стетлер кредит для этого сценария, так как он основан на его.

вот сценарий 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"

на основе ответа Джеффа Хиллмана:

вот функция, которую вы можете просто добавить в свой 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 + "'")
    }
}

допустим, вы хотите удалить Блокнот++. Просто введите это в PowerShell:

> uninstall("notepad++")

просто знайте, что Get-WmiObject может занять некоторое время, поэтому будьте терпеливы!

использование:

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. не добавляя идентификаторы к вызову функции в скрипт, вместо запуска скрипта с идентификаторами параметров
  2. вызов скрипта с более чем 1 имя компьютера не автоматически извлекается из функции
  3. извлечение данных из трубы
  4. использование IP-адресов для подключения к системе

чего он не делает:

  1. он не дает никакой информации, если программное обеспечение на самом деле было найдено на любой данной системе.
  2. он не дает никаких информация о сбое или успешном завершении деинсталляции.

Я не смог использовать uninstall(). Попытка, что я получил сообщение об ошибке, говорящее мне, что вызов метода для выражения, которое имеет значение NULL не возможно. Вместо этого я использовал Remove-WmiObject, который, кажется, выполняет то же самое.

осторожностью: без имени компьютера он удаляет программное обеспечение из все системы в Active Directory.

для большинства моих программ скрипты в этом посте сделали свою работу. Но мне пришлось столкнуться с устаревшей программой, которую я не мог удалить с помощью msiexec.класс exe или Win32_Product. (по какой-то причине я получил выход 0, но программа все еще была там)

мое решение было использовать класс Win32_Process:

С помощью nickdnk эта команда должна получить файл exe удаления путь:

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

вам придется очистить строку результата:

$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, но я считаю, что добавление аргумент -имя_компьютера может работать