Esiste un modo semplice per agganciare la funzionalità standard " Installazione applicazioni " utilizzando PowerShell per disinstallare un'applicazione esistente ? O per verificare se l'applicazione è installata?
Esiste un modo semplice per agganciare la funzionalità standard " Installazione applicazioni " utilizzando PowerShell per disinstallare un'applicazione esistente ? O per verificare se l'applicazione è installata?
Risposte:
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "Software Name"
}
$app.Uninstall()
Modifica: Rob ha trovato un altro modo per farlo con il parametro Filter:
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
(gwmi Win32_Product | ? Name -eq "Software").uninstall()
Un piccolo codice golf.
EDIT: Nel corso degli anni questa risposta ha ottenuto parecchi voti. Vorrei aggiungere alcuni commenti. Da allora non utilizzo PowerShell, ma ricordo di aver osservato alcuni problemi:
-First 1
ma non ne sono sicuro. Sentiti libero di modificare.L'uso dell'oggetto WMI richiede un'eternità. Questo è molto veloce se conosci solo il nome del programma che desideri disinstallare.
$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*"
perché la versione è nel nome e cambia, ma non sembra trovare il programma. Qualche idea?
Per sistemare il secondo metodo nel post di Jeff Hillman, puoi fare un:
$app = Get-WmiObject
-Query "SELECT * FROM Win32_Product WHERE Name = 'Software Name'"
O
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
Ho scoperto che la classe Win32_Product non è consigliata perché attiva le riparazioni e non è ottimizzata per le query. fonte
Ho trovato questo post di Sitaram Pamarthi con uno script da disinstallare se conosci l'app guid. Fornisce anche un altro script per cercare app molto velocemente qui .
Utilizzare in questo modo:. \ 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"}
}
Per aggiungere un po 'a questo post, dovevo essere in grado di rimuovere il software da più server. Ho usato la risposta di Jeff per guidarmi a questo:
Per prima cosa ho ottenuto un elenco di server, ho usato una query AD , ma puoi fornire l'array di nomi di computer come desideri:
$computers = @("computer1", "computer2", "computer3")
Poi li ho passati in loop, aggiungendo il parametro -computer alla query gwmi:
foreach($server in $computers){
$app = Get-WmiObject -Class Win32_Product -computer $server | Where-Object {
$_.IdentifyingNumber -match "5A5F312145AE-0252130-432C34-9D89-1"
}
$app.Uninstall()
}
Ho usato la proprietà IdentifyingNumber per abbinare invece di nome, solo per essere sicuro che stavo disinstallando l'applicazione corretta.
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
}
}
}
}
}
Chiamalo in questo modo:
Uninstall-App "Autodesk Revit DB Link 2019"
Una riga di codice:
get-package *notepad* |% { & $_.Meta.Attributes["UninstallString"]}
Farò il mio piccolo contributo. Avevo bisogno di rimuovere un elenco di pacchetti dallo stesso computer. Questa è la sceneggiatura che mi è venuta in mente.
$packages = @("package1", "package2", "package3")
foreach($package in $packages){
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "$package"
}
$app.Uninstall()
}
Spero che questo si riveli utile.
Nota che devo a David Stetler il merito di questo script poiché si basa sul suo.
Ecco lo script di PowerShell usando 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"
Basato sulla risposta di Jeff Hillman:
Ecco una funzione che puoi semplicemente aggiungere alla tua profile.ps1
o definire nella sessione corrente di 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 + "'")
}
}
Diciamo che volevi disinstallare Notepad ++ . Basta digitare questo in PowerShell:
> uninstall("notepad++")
Basta essere consapevoli del fatto che Get-WmiObject
può richiedere del tempo, quindi sii paziente!
Uso:
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}"
Non è completamente testato, ma è stato eseguito con PowerShell 4.
Ho eseguito il file PS1 come è visto qui. Consentendo di recuperare tutti i sistemi dall'AD e provare a disinstallare più applicazioni su tutti i sistemi.
Ho usato il numero di identificazione per cercare la causa del software dell'input di David Stetlers.
Non testato:
Cosa non fa:
Non sono stato in grado di utilizzare uninstall (). Provando a ricevere un errore che mi dice che non è possibile chiamare un metodo per un'espressione che ha un valore NULL. Invece ho usato Remove-WmiObject, che sembra realizzare lo stesso.
ATTENZIONE : senza un nome computer dato, il software viene rimosso da TUTTI i sistemi in Active Directory.
Per la maggior parte dei miei programmi gli script in questo post hanno fatto il lavoro. Ma ho dovuto affrontare un programma legacy che non potevo rimuovere usando la classe msiexec.exe o Win32_Product. (per qualche motivo ho ottenuto l'uscita 0 ma il programma era ancora lì)
La mia soluzione era usare la classe Win32_Process:
con l'aiuto di nickdnk questo comando serve per ottenere il percorso del file exe di disinstallazione:
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
dovrai pulire la stringa del risultato:
$uninstallPath = $unInstallPathReg[0].UninstallString
$uninstallPath = $uninstallPath -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
$uninstallPath = $uninstallPath .Trim()
ora quando si dispone del relativo programma disinstallare il percorso del file exe è possibile utilizzare questo comando:
$uninstallResult = (Get-WMIObject -List -Verbose | Where-Object {$_.Name -eq "Win32_Process"}).InvokeMethod("Create","$unInstallPath")
$ uninstallResult - avrà il codice di uscita. 0 è successo
i comandi precedenti possono anche essere eseguiti in remoto - l'ho fatto usando il comando invoke ma credo che l'aggiunta dell'argomento -computername possa funzionare