Существует ли простой способ подключиться к стандартной функции « Установка и удаление программ » с помощью PowerShell для удаления существующего приложения ? Или проверить, установлено ли приложение?
Существует ли простой способ подключиться к стандартной функции « Установка и удаление программ » с помощью 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'"
(gwmi Win32_Product | ? Name -eq "Software").uninstall()
Немного кода гольф.
РЕДАКТИРОВАТЬ: За эти годы этот ответ получил довольно много голосов. Я хотел бы добавить несколько комментариев. С тех пор я не использовал PowerShell, но помню, что наблюдал некоторые проблемы:
-First 1
но я не уверен. Не стесняйтесь редактировать.Использование объекта 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}
-like "appNam*"
так как версия в названии, и она меняется, но, похоже, не находит программу. Любые идеи?
Чтобы исправить второй метод в посте Джеффа Хиллмана, вы можете сделать:
$app = Get-WmiObject
-Query "SELECT * FROM Win32_Product WHERE Name = 'Software Name'"
Или
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
Я обнаружил, что класс 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"}
}
Чтобы добавить немного к этому посту, мне нужно было иметь возможность удалять программное обеспечение с нескольких серверов. Я использовал ответ Джеффа, чтобы привести меня к этому:
Сначала я получил список серверов, я использовал запрос 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 для сопоставления вместо имени, просто чтобы убедиться, что удаляю правильное приложение.
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"
Одна строка кода:
get-package *notepad* |% { & $_.Meta.Attributes["UninstallString"]}
Я сделаю свой маленький вклад. Мне нужно было удалить список пакетов с того же компьютера. Это сценарий, который я придумал.
$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 + "'")
}
}
Допустим, вы хотели удалить Notepad ++ . Просто введите это в 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 для поиска причины программного обеспечения ввода Дэвида Стетлерса.
Не проверено:
Что это не так:
Я не смог использовать 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, но я считаю, что добавление аргумента -computername может работать