PowerShellを使用してアプリケーションをアンインストールするにはどうすればよいですか?


136

PowerShellを使用して標準の「プログラム追加と削除」機能をフックして既存のアプリケーションアンインストールする簡単な方法はありますかか?または、アプリケーションがインストールされているかどうかを確認するには?

回答:


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

$app.Uninstall()

編集:ロブは、フィルターパラメーターでそれを行う別の方法を見つけました。

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

1
これはほとんどそれです、念のため、名前よりもIdentificationingNumberを使用する方が良いかもしれません。
バスタブ

6
少し調べたら、Get-WmiObjectの-filter句を使用することもできます。$ app = Get-WmiObject -Class Win32_Product -filter "select * from Win32_Product WHERE name = 'Software Name'"
Rob Paterson

8
WMIを表示しても、MSIを介してインストールされた製品でのみ機能することに注意してください。
EBGreen 2008

7
このWMIクラスは、列挙するのにFOREVERを必要とします。ロブのヒントを含めるようにコードを更新することをジェフに提案します。
halr9000 2008

4
(gwmi Win32_Product | ? Name -eq "Software").uninstall() 少しコードゴルフ。
1

51

編集:長年にわたって、この回答はかなりの賛成票を得ています。コメントをいくつか追加したいと思います。私はそれ以来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}

1
これをありがとう!-like "appNam*"バージョンに名前が含まれていて変更されているので、これを使用しようとしていますが、プログラムが見つかりません。何か案は?
NSout

1
powershellの-like関数を検索し、文字列に正しく一致させる方法を使用するフィルターを見つけます。ただ、テストにシェルを使用して、あなたがそれを得れば右-match :)置き換える
nickdnk

2
これは金です。個人的には、「/ qb」から「b」を削除して、ダイアログを表示する必要がないようにします。
WhiteHotLoveTiger

はるかに迅速:-)
オスカーフォーリー

3
これを.ps1スクリプトに変換し、プロンプトと「アンインストールしようとしているもの」の情報を追加しました。gist.github.com/chrisfcarroll/e38b9ffcc52fa9d4eb9ab73b13915f5a
クリス・F・キャロル

34

Jeff Hillmanの投稿の2番目の方法を修正するには、次のいずれかを実行できます。

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

または

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

ただの注意点...「-Filter」オプションの代わりに「-Query」を使用してもWmiObjectが返されないため、「uninstall」メソッドがないことがわかりました。
Doug J. Huras 2017

7

Win32_Productクラスは修復をトリガーし、クエリ最適化されないため、推奨されないことがわかりました。ソース

アプリGUIDを知っている場合にアンインストールするスクリプトを含む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"}
 }

7

この投稿に少し追加するには、複数のサーバーからソフトウェアを削除できる必要がありました。私はこれに私を導くためにジェフの答えを使いました:

最初にサーバーのリストを取得し、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()
}

正しいアプリケーションをアンインストールしていることを確認するために、名前の代わりに照合するためにIdentificationingNumberプロパティを使用しました。


単にこのソリューションが素敵
Raffaeu 2014

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


3

私は少しだけ貢献します。同じコンピューターからパッケージのリストを削除する必要がありました。これは私が思いついたスクリプトです。

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

これがお役に立てば幸いです。

このスクリプトは彼に基づいているため、私はこのスクリプトのクレジットをDavid Stetlerに負っていることに注意してください。


2

次に、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"

このアプローチを次のフラグと組み合わせました。何らかの理由で、これは他のアプローチよりもうまく機能します。
デビッドロジャース

1

ジェフ・ヒルマンの答えに基づいて:

これ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しばらく時間がかかることがありますので、しばらくお待ちください。


0

使用する:

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からすべてのシステムを取得させ、すべてのシステム上の複数のアプリケーションをアンインストールしようとします。

Identification Numberを使用して、David Stetlersの入力のソフトウェア原因を検索しました。

未検証:

  1. スクリプトの関数の呼び出しにIDを追加せず、代わりにパラメーターIDを使用してスクリプトを開始する
  2. 関数から自動的に取得されない複数のコンピューター名でスクリプトを呼び出す
  3. パイプからデータを取得する
  4. IPアドレスを使用してシステムに接続する

しないこと:

  1. ソフトウェアが特定のシステムで実際に見つかった場合、情報は提供されません。
  2. 削除の失敗または成功に関する情報は提供されません。

uninstall()を使用できませんでした。NULLの値を持つ式のメソッドを呼び出すことができないことを伝えるエラーが発生したことを試してみました。代わりに、Remove-WmiObjectを使用しましたが、これは同じことを達成しているようです。

注意:コンピュータ名を指定しないと、Active Directory内のすべてのシステムからソフトウェアが削除されます。


0

ほとんどの私のプログラムでは、この投稿のスクリプトがその役目を果たしました。しかし、私は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を追加するとうまくいくと思います

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.