¿Hay una manera simple de conectarse a la funcionalidad estándar ' Agregar o quitar programas ' usando PowerShell para desinstalar una aplicación existente ? ¿O para verificar si la aplicación está instalada?
¿Hay una manera simple de conectarse a la funcionalidad estándar ' Agregar o quitar programas ' usando PowerShell para desinstalar una aplicación existente ? ¿O para verificar si la aplicación está instalada?
Respuestas:
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "Software Name"
}
$app.Uninstall()
Editar: Rob encontró otra forma de hacerlo con el parámetro Filtro:
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
(gwmi Win32_Product | ? Name -eq "Software").uninstall()
Un pequeño código de golf.
EDITAR: a lo largo de los años, esta respuesta ha recibido bastantes votos a favor. Me gustaría agregar algunos comentarios. Desde entonces no he usado PowerShell, pero recuerdo haber observado algunos problemas:
-First 1
pero no estoy seguro. Siéntase libre de editar.Usar el objeto WMI lleva una eternidad. Esto es muy rápido si solo conoce el nombre del programa que desea desinstalar.
$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*"
ya que la versión está en el nombre y cambia, pero no parece encontrar el programa. ¿Algunas ideas?
Para arreglar el segundo método en la publicación de Jeff Hillman, puedes hacer lo siguiente:
$app = Get-WmiObject
-Query "SELECT * FROM Win32_Product WHERE Name = 'Software Name'"
O
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
Descubrí que la clase Win32_Product no se recomienda porque desencadena reparaciones y no está optimizada para consultas. Fuente
Encontré esta publicación de Sitaram Pamarthi con un script para desinstalar si conoces el guid de la aplicación. También proporciona otro script para buscar aplicaciones realmente rápido aquí .
Use así:. \ 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"}
}
Para agregar un poco a esta publicación, necesitaba poder eliminar el software de varios servidores. Usé la respuesta de Jeff para llevarme a esto:
Primero obtuve una lista de servidores, utilicé una consulta AD , pero puede proporcionar la matriz de nombres de computadora como desee:
$computers = @("computer1", "computer2", "computer3")
Luego los recorrí, agregando el parámetro -computer a la consulta gwmi:
foreach($server in $computers){
$app = Get-WmiObject -Class Win32_Product -computer $server | Where-Object {
$_.IdentifyingNumber -match "5A5F312145AE-0252130-432C34-9D89-1"
}
$app.Uninstall()
}
Utilicé la propiedad IdentifyingNumber para hacer coincidir en lugar de nombre, solo para asegurarme de que estaba desinstalando la aplicación correcta.
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
}
}
}
}
}
Llámalo de esta manera:
Uninstall-App "Autodesk Revit DB Link 2019"
Una línea de código:
get-package *notepad* |% { & $_.Meta.Attributes["UninstallString"]}
Haré mi pequeña contribución. Necesitaba eliminar una lista de paquetes de la misma computadora. Este es el guión que se me ocurrió.
$packages = @("package1", "package2", "package3")
foreach($package in $packages){
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "$package"
}
$app.Uninstall()
}
Espero que esto sea útil.
Tenga en cuenta que le debo a David Stetler el crédito por este guión, ya que se basa en el suyo.
Aquí está el script de 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"
Basado en la respuesta de Jeff Hillman:
Aquí hay una función que puede agregar profile.ps1
o definir en su sesión actual de 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 + "'")
}
}
Digamos que desea desinstalar Notepad ++ . Simplemente escriba esto en PowerShell:
> uninstall("notepad++")
Solo tenga en cuenta que Get-WmiObject
puede tomar algo de tiempo, ¡así que sea paciente!
Utilizar:
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}"
No está completamente probado, pero se ejecutó con PowerShell 4.
Ejecuté el archivo PS1 como se ve aquí. Permitiéndole recuperar todos los sistemas del AD e intentando desinstalar múltiples aplicaciones en todos los sistemas.
He utilizado el número de identificación para buscar la causa del software de la entrada de David Stetlers.
No probado:
Lo que no hace:
No pude usar desinstalar (). Al intentar obtener un error, me dice que no es posible llamar a un método para una expresión que tiene un valor de NULL. En su lugar, utilicé Remove-WmiObject, que parece lograr lo mismo.
PRECAUCIÓN : Sin un nombre de computadora dado, elimina el software de TODOS los sistemas en el Directorio Activo.
Para la mayoría de mis programas, los scripts en esta publicación hicieron el trabajo. Pero tuve que enfrentar un programa heredado que no pude eliminar usando msiexec.exe o la clase Win32_Product. (por alguna razón obtuve la salida 0 pero el programa todavía estaba allí)
Mi solución fue usar la clase Win32_Process:
con la ayuda de nickdnk, este comando es obtener la ruta de desinstalación del archivo 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
Tendrá que limpiar la cadena de resultados:
$uninstallPath = $unInstallPathReg[0].UninstallString
$uninstallPath = $uninstallPath -Replace "msiexec.exe","" -Replace "/I","" -Replace "/X",""
$uninstallPath = $uninstallPath .Trim()
ahora, cuando tenga el programa relevante desinstalar la ruta del archivo exe , puede usar este comando:
$uninstallResult = (Get-WMIObject -List -Verbose | Where-Object {$_.Name -eq "Win32_Process"}).InvokeMethod("Create","$unInstallPath")
$ uninstallResult: tendrá el código de salida. 0 es el éxito
los comandos anteriores también pueden ejecutarse de forma remota: lo hice usando el comando invoke pero creo que agregar el argumento -computername puede funcionar