source

PowerShell을 사용하여 응용 프로그램을 제거하려면 어떻게 해야 합니까?

lovecheck 2023. 5. 22. 21:10
반응형

PowerShell을 사용하여 응용 프로그램을 제거하려면 어떻게 해야 합니까?

PowerShell을 사용하여 기존 응용 프로그램을 제거하는 표준 '프로그램 추가/제거' 기능에 연결하는 간단한 방법이 있습니까?또는 응용 프로그램이 설치되어 있는지 확인하기 위해?

$app = Get-WmiObject -Class Win32_Product | Where-Object { 
    $_.Name -match "Software Name" 
}

$app.Uninstall()

편집: Rob은 필터 매개 변수를 사용하여 다른 방법을 찾았습니다.

$app = Get-WmiObject -Class Win32_Product `
                     -Filter "Name = 'Software Name'"

편집: 지난 몇 년간 이 답변은 꽤 많은 지지를 받았습니다.저는 몇 가지 의견을 추가하고 싶습니다.그 이후로 PowerShell을 사용하지는 않았지만 다음과 같은 몇 가지 문제를 관찰한 기억이 있습니다.

  1. 아래 스크립트에 일치하는 항목이 1개보다 많으면 해당 스크립트가 작동하지 않으므로 결과를 1로 제한하는 PowerShell 필터를 추가해야 합니다.는 그것이 저는그라고 .-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}

Jeff Hillman의 게시물에서 두 번째 방법을 수정하려면 다음 중 하나를 수행할 수 있습니다.

$app = Get-WmiObject 
            -Query "SELECT * FROM Win32_Product WHERE Name = 'Software Name'"

또는

$app = Get-WmiObject -Class Win32_Product `
                     -Filter "Name = 'Software Name'"

코드 한 줄:

get-package *notepad* |% { & $_.Meta.Attributes["UninstallString"]}
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"

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

이 게시물에 조금 더 추가하려면 여러 서버에서 소프트웨어를 제거할 수 있어야 했습니다.저는 제프의 대답을 통해 이렇게 이끌었습니다.

처음에 서버 목록을 받았고 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 속성을 사용하여 비교했습니다.

다음은 msiexec을 사용하는 PowerShell 스크립트입니다.

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"

나는 나만의 작은 기여를 할 것입니다.동일한 컴퓨터에서 패키지 목록을 제거해야 했습니다.이것이 제가 생각해 낸 대본입니다.

$packages = @("package1", "package2", "package3")
foreach($package in $packages){
  $app = Get-WmiObject -Class Win32_Product | Where-Object {
    $_.Name -match "$package"
  }
  $app.Uninstall()
}

저는 이것이 유용하다는 것이 증명되기를 바랍니다.

이 대본은 데이비드 스테틀러에 기반을 두고 있기 때문에 저는 데이비드 스테틀러에게 공을 돌려야 합니다.

Jeff Hillman의 답변을 토대로 합니다.

의 여에다기추수있다습니가할에 할 수 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 파일을 실행했습니다.AD에서 모든 시스템을 검색하고 모든 시스템에서 여러 응용 프로그램을 제거합니다.

식별 번호를 사용하여 David Stetlers 입력의 소프트웨어 원인을 검색했습니다.

테스트되지 않음:

  1. 스크립트에서 함수 호출에 ID를 추가하지 않고 매개 변수 ID로 스크립트 시작
  2. 컴퓨터 이름이 둘 이상인 스크립트를 호출하면 함수에서 자동으로 검색되지 않습니다.
  3. 파이프에서 데이터 검색
  4. IP 주소를 사용하여 시스템에 연결

하지 않는 것:

  1. 소프트웨어가 실제로 특정 시스템에서 발견되었는지 여부에 대한 정보를 제공하지 않습니다.
  2. 제거 실패 또는 성공에 대한 정보는 제공되지 않습니다.

제거()를 사용할 수 없습니다.값이 NULL인 식에 대해 메서드를 호출할 수 없다는 오류가 발생했습니다.대신 Remove-WmiObject를 사용했는데, 이는 동일한 작업을 수행하는 것으로 보입니다.

주의:컴퓨터 이름을 지정하지 않으면 Active Directory의 모든 시스템에서 소프트웨어가 제거됩니다.

대부분의 프로그램에서 이 포스트의 스크립트가 수행했습니다.하지만 저는 msiexec을 사용하여 제거할 수 없는 레거시 프로그램에 직면해야 했습니다.exe 또는 Win32_Product 클래스입니다.(어떤 이유에서 0번 출구를 얻었지만 프로그램은 여전히 그곳에 있었습니다)

솔루션은 Win32_Process 클래스를 사용하는 것이었습니다.

nickdnk의 도움을 받아 이 명령은 제거 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은 성공입니다.

위의 명령도 원격으로 실행할 수 있습니다 - 나는 invoke 명령을 사용하여 수행했지만 -computername 인수를 추가하면 작동할 수 있다고 생각합니다.

msi 설치의 경우 "uninstall-package why"가 제대로 작동합니다.msi가 아닌 설치(프로그램 공급자)의 경우 문자열 구문 분석이 더 많이 필요합니다.제거 exe가 공백이 있는 경로에 있고 이중 따옴표로 묶인 경우에도 이 점이 고려되어야 합니다.설치 패키지는 msi에서도 작동합니다.

$uninstall = get-package whatever | % { $_.metadata['uninstallstring'] }
# split quoted and unquoted things on whitespace
$prog, $myargs = $uninstall | select-string '("[^"]*"|\S)+' -AllMatches | 
  % matches | % value
$prog = $prog -replace '"',$null  # call & operator doesn't like quotes
$silentoption = '/S'
$myargs += $silentoption  # add whatever silent uninstall option
& $prog $myargs  # run uninstaller silently

어쨌든 기다려야 하는 경우에는 시작 프로세스가 큰따옴표를 신경 쓰지 않습니다.

# "C:\Program Files (x86)\myapp\unins000.exe"
get-package myapp | foreach { start -wait $_.metadata['uninstallstring'] /SILENT }

최신 윈도우즈 시스템에서는 다음을 사용하여 설치된 msi 소프트웨어를 제거할 수 있습니다.$pkg도 확인할 수 있습니다.공급자 이름 - EQ "msi"(원하는 경우).

$pkg = get-package *name*
$prodCode = "{" + $pkg.TagId + "}"
msiexec.exe /X $prodCode /passive

언급URL : https://stackoverflow.com/questions/113542/how-can-i-uninstall-an-application-using-powershell

반응형