Вопрос

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

Это было полезно?

Решение

$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'"

Другие советы

РЕДАКТИРОВАТЬ:За прошедшие годы этот ответ получил довольно много голосов.Я хотел бы добавить несколько комментариев.С тех пор я не использовал 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'"

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

Сначала я получил список серверов, я использовал ОБЪЯВЛЕНИЕ запрос, но вы можете предоставить массив имен компьютеров по своему усмотрению:

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

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

Я обнаружил, что класс Win32_Product не рекомендуется использовать, поскольку он вызывает ремонт и не оптимизирован для запросов. Источник

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

Используйте вот так:. 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"}
 }
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"

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

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

Одна строка кода:

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

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

Вот функция, которую вы можете просто добавить в свой 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, как показано здесь.Позволив ему получить все системы из ОБЪЯВЛЕНИЕ и пытаюсь удалить несколько приложений во всех системах.

Я использовал идентификационный номер для поиска причины программного обеспечения, введенной Дэвидом Стетлерсом.

Не испытано:

  1. Не добавлять идентификаторы при вызове функции в скрипте, а запускать скрипт с идентификаторами параметров
  2. Вызов сценария с более чем 1 именем компьютера нет автоматически извлекается из функции
  3. Получение данных из канала
  4. Использование IP-адресов для подключения к системе

Чего нет:

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

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

ОСТОРОЖНОСТЬ:Без указания имени компьютера программное обеспечение удаляется из ВСЕ системы в Active Directory.

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

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

с помощью Никдонк эта команда предназначена для получения пути к 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 — успех

приведенные выше команды также можно запускать удаленно — я сделал это с помощью команды вызова, но считаю, что добавление аргумента -имя_компьютера может сработать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top