PowerShell を使用してアプリケーションをアンインストールするにはどうすればよいですか?
-
02-07-2019 - |
質問
標準にフックする簡単な方法はありますか?プログラムの追加または削除' PowerShell を使用した機能 既存のアプリケーションをアンインストールする?それともアプリケーションがインストールされているかどうかを確認しますか?
解決
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "Software Name"
}
$app.Uninstall()
編集: ロブは、Filter パラメーターを使用して別の方法を見つけました。
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
他のヒント
編集:長年にわたって、この回答はかなりの数の賛成票を集めてきました。いくつかコメントを追加したいと思います。それ以来、PowerShell を使用していませんが、いくつかの問題を観察したことを覚えています。
- 以下のスクリプトに一致するものが 1 つよりも多い場合、スクリプトは機能しないため、結果を 1 に制限する PowerShell フィルターを追加する必要があります。そうだと思います
-First 1
確信はないけど。ご自由に編集してください。 - アプリケーションが 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 の投稿の 2 番目の方法を修正するには、次のいずれかを実行できます。
$app = Get-WmiObject
-Query "SELECT * FROM Win32_Product WHERE Name = 'Software Name'"
または
$app = Get-WmiObject -Class Win32_Product `
-Filter "Name = 'Software Name'"
この投稿に少し追加すると、複数のサーバーからソフトウェアを削除できる必要がありました。私は Jeff の答えを使用してこれに導きました。
まずサーバーのリストを取得し、使用しました 広告 クエリを実行しますが、必要に応じてコンピュータ名の配列を指定できます。
$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 プロパティを使用して照合しました。
Win32_Product クラスは修復をトリガーし、クエリが最適化されていないため、推奨されないことがわかりました。 ソース
見つけました この郵便受け Sitaram Pamarthi から、アプリ GUID がわかっている場合にアンインストールするスクリプトが含まれています。彼は、アプリを非常に高速に検索するための別のスクリプトも提供しています。 ここ.
次のように使用します。。 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"}
}
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"
私自身も微力ながら貢献させていただきます。同じコンピューターからパッケージのリストを削除する必要がありました。これが私が思いついたスクリプトです。
$packages = @("package1", "package2", "package3")
foreach($package in $packages){
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "$package"
}
$app.Uninstall()
}
これが役立つことを願っています。
この脚本は David Stetler の著作に基づいているため、私は David Stetler の功績であることに注意してください。
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 行のコード:
get-package *notepad* |% { & $_.Meta.Attributes["UninstallString"]}
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 ファイルを実行しました。すべてのシステムを 広告 すべてのシステムで複数のアプリケーションをアンインストールしようとしています。
IdentifyingNumber を使用して、David Stetlers 入力のソフトウェア原因を検索しました。
未検証:
- スクリプト内の関数の呼び出しに ID を追加せず、代わりにパラメーター ID を使用してスクリプトを開始します。
- 複数のコンピュータ名を使用してスクリプトを呼び出す ない 関数から自動的に取得される
- パイプからデータを取得する
- IP アドレスを使用してシステムに接続する
できないこと:
- ソフトウェアが特定のシステム上で実際に見つかった場合には、情報は提供されません。
- アンインストールの失敗または成功に関する情報は提供されません。
uninstall()が使えませんでした。それを試してみると、NULL の値を持つ式のメソッドを呼び出すことはできないというエラーが発生しました。代わりに、同じことを達成できるように見える Remove-WmiObject を使用しました。
注意:コンピュータ名を指定しないと、ソフトウェアが削除されます。 全て Active Directory 内のシステム。
私のプログラムのほとんどは、この投稿のスクリプトでうまくいきました。しかし、msiexec.exe や Win32_Product クラスを使用して削除できないレガシー プログラムに直面する必要がありました。(何らかの理由で exit 0 に到達しましたが、プログラムはまだそこにありました)
私の解決策は、Win32_Process クラスを使用することでした。
~の助けを借りて ニックンク このコマンドは、アンインストール 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 を追加すると機能すると思います。