Czy istnieje prosty sposób na podłączenie się do standardowej funkcji „ Dodaj lub usuń programy ” przy użyciu programu PowerShell w celu odinstalowania istniejącej aplikacji ? Albo sprawdzić, czy aplikacja jest zainstalowana?
Czy istnieje prosty sposób na podłączenie się do standardowej funkcji „ Dodaj lub usuń programy ” przy użyciu programu PowerShell w celu odinstalowania istniejącej aplikacji ? Albo sprawdzić, czy aplikacja jest zainstalowana?
Odpowiedzi:
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "Software Name"
}
$app.Uninstall()
Edycja: Rob znalazł inny sposób na zrobienie tego z parametrem Filter:
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
(gwmi Win32_Product | ? Name -eq "Software").uninstall()
Mały golf kodowy.
EDYCJA: Na przestrzeni lat ta odpowiedź zyskała kilka pozytywnych głosów. Chciałbym dodać kilka komentarzy. Od tego czasu nie korzystałem z PowerShell, ale pamiętam, że zauważyłem kilka problemów:
-First 1
ale nie jestem pewien. Zapraszam do edycji.Korzystanie z obiektu WMI trwa wiecznie. Jest to bardzo szybkie, jeśli znasz tylko nazwę programu, który chcesz odinstalować.
$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*"
ponieważ wersja jest w nazwie i zmienia się, ale wydaje się, że nie można znaleźć programu. Jakieś pomysły?
Aby naprawić drugą metodę w poście Jeffa Hillmana, możesz wykonać:
$app = Get-WmiObject
-Query "SELECT * FROM Win32_Product WHERE Name = 'Software Name'"
Lub
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
Dowiedziałem się, że klasa Win32_Product nie jest zalecana, ponieważ wyzwala naprawy i nie jest zoptymalizowana pod kątem zapytań. Źródło
Znalazłem ten post od Sitaram Pamarthi ze skryptem do odinstalowania, jeśli znasz przewodnik po aplikacji. On również dostarcza inny skrypt do wyszukiwania aplikacji bardzo szybko tutaj .
Użyj w ten sposób:. \ 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"}
}
Aby trochę dodać do tego postu, potrzebowałem możliwości usuwania oprogramowania z wielu serwerów. Użyłem odpowiedzi Jeffa, aby doprowadzić mnie do tego:
Najpierw otrzymałem listę serwerów, użyłem zapytania AD , ale możesz podać tablicę nazw komputerów, jak chcesz:
$computers = @("computer1", "computer2", "computer3")
Następnie przejrzałem je, dodając parametr -computer do zapytania gwmi:
foreach($server in $computers){
$app = Get-WmiObject -Class Win32_Product -computer $server | Where-Object {
$_.IdentifyingNumber -match "5A5F312145AE-0252130-432C34-9D89-1"
}
$app.Uninstall()
}
Użyłem właściwości IdentifyingNumber do dopasowania zamiast nazwy, aby upewnić się, że odinstalowałem odpowiednią aplikację.
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
}
}
}
}
}
Nazwij to w ten sposób:
Uninstall-App "Autodesk Revit DB Link 2019"
Jedna linia kodu:
get-package *notepad* |% { & $_.Meta.Attributes["UninstallString"]}
Dokonam niewielkiego wkładu własnego. Musiałem usunąć listę pakietów z tego samego komputera. To jest scenariusz, który wymyśliłem.
$packages = @("package1", "package2", "package3")
foreach($package in $packages){
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "$package"
}
$app.Uninstall()
}
Mam nadzieję, że okaże się to przydatne.
Zauważ, że jestem winien Davidowi Stetlerowi uznanie za ten skrypt, ponieważ jest on oparty na jego.
Oto skrypt PowerShell używający 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"
Na podstawie odpowiedzi Jeffa Hillmana:
Oto funkcja, którą możesz po prostu dodać do swojej profile.ps1
lub zdefiniować w bieżącej sesji 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 + "'")
}
}
Powiedzmy, że chcesz odinstalować Notepad ++ . Po prostu wpisz to w PowerShell:
> uninstall("notepad++")
Pamiętaj tylko, że Get-WmiObject
może to zająć trochę czasu, więc bądź cierpliwy!
Posługiwać się:
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}"
Nie jest w pełni przetestowany, ale działał pod PowerShell 4.
Uruchomiłem plik PS1, jak widać tutaj. Pozwalając mu pobrać wszystkie systemy z AD i próbując odinstalować wiele aplikacji we wszystkich systemach.
Użyłem numeru identyfikacyjnego do wyszukania przyczyny oprogramowania danych wejściowych Davida Stetlera.
Nie testowany:
Czego to nie robi:
Nie mogłem użyć uninstall (). Próbując uzyskać błąd informujący mnie, że wywołanie metody dla wyrażenia, które ma wartość NULL, nie jest możliwe. Zamiast tego użyłem Remove-WmiObject, który wydaje się osiągać to samo.
UWAGA : Bez podania nazwy komputera usuwa oprogramowanie ze WSZYSTKICH systemów w usłudze Active Directory.
W przypadku większości moich programów skrypty w tym poście spełniły swoje zadanie. Ale musiałem zmierzyć się ze starszym programem, którego nie mogłem usunąć za pomocą klasy msiexec.exe lub Win32_Product. (z jakiegoś powodu dostałem wyjście 0, ale program wciąż tam był)
Moim rozwiązaniem było użycie klasy Win32_Process:
z pomocą nickdnk ta komenda pozwala uzyskać ścieżkę do pliku deinstalacyjnego exe:
64-bitowy:
[array]$unInstallPathReg= gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match $programName } | select UninstallString
32-bitowy:
[array]$unInstallPathReg= gci "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -match $programName } | select UninstallString
będziesz musiał wyczyścić ciąg wynikowy:
$uninstallPath = $unInstallPathReg[0].UninstallString
$uninstallPath = $uninstallPath -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
$uninstallPath = $uninstallPath .Trim()
teraz, gdy masz odpowiednią ścieżkę do pliku deinstalacji programu exe , możesz użyć tego polecenia:
$uninstallResult = (Get-WMIObject -List -Verbose | Where-Object {$_.Name -eq "Win32_Process"}).InvokeMethod("Create","$unInstallPath")
$ uninstallResult - będzie mieć kod zakończenia. 0 to sukces
powyższe polecenia można również uruchomić zdalnie - zrobiłem to za pomocą polecenia invoke, ale uważam, że dodanie argumentu -computername może działać