日程Fit|「いつ空いてますか?」の往復はもう不要。候補日を選んでURLを送るだけ|登録不要|今すぐ無料で使う →

PowerShellで特定のアプリケーションがインストールされているか確認する方法

PowerShellで特定のアプリケーションがインストールされているか確認する方法という問いには、Get-AppxPackageとアンインストール用レジストリを読み取り専用で取得し、製品名、発行元、版、識別子を照合するという方法で答えます。Get-AppxPackageだけではMSIやEXEで導入した製品を網羅できず、HKLMの64bit側とWOW6432Node、必要ならHKCUを別々に読む。Win32_Productの列挙はMSIの整合性確認を誘発する可能性があるため棚卸しには使わない。この記事ではStoreアプリはPackageFullName、従来型アプリはアンインストールキーのPSPathとDisplayNameで識別するを判断軸にし、実行前の確認、記事固有のコード、合否判定、戻し方を一続きで示します。

この記事は導入有無の正確な棚卸しに限定し、アプリの削除やパッケージ配布は扱わない。完了は「探している製品の発行元と版が要件に一致し、どのユーザーまたはコンピューター範囲に導入されたか説明できる」と定義します。対象が取れない場合は「0件でも即座に未導入とはしない。表示名の違い、ユーザー範囲、32bit側、ポータブル版の順で確認する」として切り分け、推測で成功扱いにしません。

日程Fit。無料・登録不要。「いつ空いてる?」を、ひとつのリンクで。リンクを送って、○△×でかんたん日程調整。無料で日程を作る。
目次

Storeアプリとデスクトップアプリは別の台帳で探す

Storeアプリとデスクトップアプリは別の台帳で探すでは、インストール済みアプリの棚卸しの対象を「StoreアプリはPackageFullName、従来型アプリはアンインストールキーのPSPathとDisplayNameで識別する」という単位で扱います。Get-AppxPackageだけではMSIやEXEで導入した製品を網羅できず、HKLMの64bit側とWOW6432Node、必要ならHKCUを別々に読む。Win32_Productの列挙はMSIの整合性確認を誘発する可能性があるため棚卸しには使わない。対象が複数なら表示名の部分一致で先頭を採らず、一意になる条件を追加します。

インストール済みアプリの棚卸しを始める前に、PowerShellの版、コマンドの提供元、必要権限、管理ポリシーの有無を確認します。権限不足と対象なしは意味が異なるため、例外を0件へ置き換えません。

確認対象を製品名だけで決めない

Get-AppxPackageとアンインストール用レジストリを読み取り専用で取得し、製品名、発行元、版、識別子を照合する。インストール済みアプリの棚卸しではこの進め方により、操作したという事実ではなく、期待する状態へ到達したかでタイトルの問いへ答えられます。この記事は導入有無の正確な棚卸しに限定し、アプリの削除やパッケージ配布は扱わない。

確認対象を製品名だけで決めないの合格条件は、探している製品の発行元と版が要件に一致し、どのユーザーまたはコンピューター範囲に導入されたか説明できることです。作業時刻、実行ユーザー、端末名を添え、判断に使った値が後から追える形にします。

再構成を招くWin32_Productを避ける

再構成を招くWin32_Productを避けるは変更前の基準点です。StoreアプリはPackageFullName、従来型アプリはアンインストールキーのPSPathとDisplayNameで識別するを出力に含め、取得時刻と一緒に保存します。値だけを切り取ると別対象との比較になるため、識別列を省きません。

$uninstallSubKey = 'Software\Microsoft\Windows\CurrentVersion\Uninstall'
$locations = @(
  [pscustomobject]@{ Scope='Machine'; View=[Microsoft.Win32.RegistryView]::Registry64; Hive=[Microsoft.Win32.RegistryHive]::LocalMachine }
  [pscustomobject]@{ Scope='Machine'; View=[Microsoft.Win32.RegistryView]::Registry32; Hive=[Microsoft.Win32.RegistryHive]::LocalMachine }
  [pscustomobject]@{ Scope='CurrentUser'; View=[Microsoft.Win32.RegistryView]::Registry64; Hive=[Microsoft.Win32.RegistryHive]::CurrentUser }
  [pscustomobject]@{ Scope='CurrentUser'; View=[Microsoft.Win32.RegistryView]::Registry32; Hive=[Microsoft.Win32.RegistryHive]::CurrentUser }
)
$desktopApps = @(
  foreach ($location in $locations) {
    $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey($location.Hive, $location.View)
    try {
      $uninstall = $base.OpenSubKey($uninstallSubKey)
      if ($null -eq $uninstall) { continue }
      try {
        foreach ($subName in $uninstall.GetSubKeyNames()) {
          $item = $uninstall.OpenSubKey($subName)
          try {
            $displayName = [string]$item.GetValue('DisplayName')
            if ([string]::IsNullOrWhiteSpace($displayName)) { continue }
            [pscustomobject]@{
              Source='Desktop'; Scope=$location.Scope; RegistryView=[string]$location.View
              DisplayName=$displayName; DisplayVersion=[string]$item.GetValue('DisplayVersion')
              Publisher=[string]$item.GetValue('Publisher')
              RegistryPath="$($location.Hive)\$($location.View)\$uninstallSubKey\$subName"
            }
          } finally {
            if ($null -ne $item) { $item.Dispose() }
          }
        }
      } finally { $uninstall.Dispose() }
    } finally { $base.Dispose() }
  }
)

Get-AppxPackageだけではMSIやEXEで導入した製品を網羅できず、HKLMの64bit側とWOW6432Node、必要ならHKCUを別々に読む。Win32_Productの列挙はMSIの整合性確認を誘発する可能性があるため棚卸しには使わない。出力が多い場合も最初から無理に一件へ絞らず、候補数と除外理由を残してから対象を決めます。

二つの取得結果を同じ列へそろえる

二つの取得結果を同じ列へそろえるでは同じ対象を別経路でもう一度読みます。判定したいのは「コマンドが終了したか」ではなく、探している製品の発行元と版が要件に一致し、どのユーザーまたはコンピューター範囲に導入されたか説明できるかどうかです。

$wantedName = 'Contoso Agent'
$wantedPublisher = 'Contoso Ltd.'
$desktopMatches = @($desktopApps | Where-Object {
  $_.DisplayName -eq $wantedName -and $_.Publisher -eq $wantedPublisher
})
$coverage = $locations | Select-Object Scope, View
if ($desktopMatches.Count -eq 0) {
  Write-Warning '4経路では未検出です。ポータブル版や別表示名を確認するまで未導入とは断定しません。'
}
[pscustomobject]@{
  QueriedRegistryLocations = $coverage.Count
  MatchCount = $desktopMatches.Count
  Result = if ($desktopMatches.Count) { 'Detected' } else { 'NotDetectedInCoveredRegistries' }
}
$desktopMatches | Format-Table Scope, RegistryView, DisplayName, DisplayVersion, Publisher

0件でも即座に未導入とはしない。表示名の違い、ユーザー範囲、32bit側、ポータブル版の順で確認する。インストール済みアプリの棚卸しの期待値と実測値が一致しないときは追加変更を重ねず、対象識別、権限、ポリシー、時間差の順で原因を分けます。

未検出を未導入と断定する前に

未検出を未導入と断定する前にでは、Get-AppxPackageとアンインストール用レジストリを読み取り専用で取得し、製品名、発行元、版、識別子を照合する。インストール済みアプリの棚卸しの例中にある名前、パス、ID、時刻はサンプルなので、そのまま本番へ貼らず、直前の読み取り結果から承認値を入れます。

$appxName = 'Microsoft.WindowsCalculator'
$storeMatches = @(Get-AppxPackage -Name $appxName -ErrorAction Stop)
$storeMatches | ForEach-Object {
  [pscustomobject]@{
    Source='Store'; Scope='CurrentUser'; Name=$_.Name
    PackageFullName=$_.PackageFullName; Version=[string]$_.Version
    Publisher=$_.Publisher; Status=$_.Status
  }
}
if ($storeMatches.Count -eq 0) {
  Write-Warning '現在ユーザー範囲では未検出です。別ユーザーや-AllUsersは権限と調査範囲を承認して別に確認します。'
}

曖昧な部分一致で別製品を合格にしたり、Win32_Productを定期実行してインストーラーを動かしたりしない。インストール済みアプリの棚卸しでプレビュー対応コマンドを使える場合はWhatIfを先に実行し、非対応の操作は対象一覧と引数を画面へ出して人が承認してから一度だけ実行します。

32bit側も含めて証跡を残す

読み取りのみなので設定の復元は不要。CSV等へ保存した場合は端末名や製品情報を含むため保管期限とアクセス権を決める。復旧操作にも同じ識別条件を使い、名前が似た別対象へ戻し処理を適用しません。

  • インストール済みアプリの棚卸しの変更前値と取得時刻
  • 復旧対象: StoreアプリはPackageFullName、従来型アプリはアンインストールキーのPSPathとDisplayNameで識別する
  • 復旧後の判定: 探している製品の発行元と版が要件に一致し、どのユーザーまたはコンピューター範囲に導入されたか説明できる
  • 再実行を止める条件: 曖昧な部分一致で別製品を合格にしたり、Win32_Productを定期実行してインストーラーを動かしたりしない

判定スクリプトへ渡せる形に整える

曖昧な部分一致で別製品を合格にしたり、Win32_Productを定期実行してインストーラーを動かしたりしない。判定スクリプトへ渡せる形に整えるに該当したら、警告を消して継続するのではなく、どの条件で止まったかを記録します。

0件でも即座に未導入とはしない。表示名の違い、ユーザー範囲、32bit側、ポータブル版の順で確認する。インストール済みアプリの棚卸しではエラー本文、FullyQualifiedErrorId、対象ID、直前に成功した段階を残すと、別担当者が安全な地点から調査できます。

PublisherとVersionまで見て完了とする

自動判定ではNameだけでなくPublisherと最低Versionを条件にし、未検出、版不足、複数候補を別の終了状態にする。インストール済みアプリの棚卸しを繰り返す場合は、正常、対象なし、要承認、失敗を異なる終了状態として記録し、前回値との比較だけで異常を決めません。

PublisherとVersionまで見て完了とするの識別軸StoreアプリはPackageFullName、従来型アプリはアンインストールキーのPSPathとDisplayNameで識別する
採用する実測探している製品の発行元と版が要件に一致し、どのユーザーまたはコンピューター範囲に導入されたか説明できる
0件時の扱い0件でも即座に未導入とはしない。表示名の違い、ユーザー範囲、32bit側、ポータブル版の順で確認する
保留にする兆候曖昧な部分一致で別製品を合格にしたり、Win32_Productを定期実行してインストーラーを動かしたりしない

インストール済みアプリの棚卸しの実行記録には、開始前の対象候補、採用した識別値、実行したコード、終了後の実測、除外した候補と理由を同じ作業番号で残します。特に「StoreアプリはPackageFullName、従来型アプリはアンインストールキーのPSPathとDisplayNameで識別する」を省くと、後日の再確認で別対象の値を比較するおそれがあります。画面コピーだけでなく、日時と端末名を含む構造化した出力も保存します。

PowerShellで特定のアプリケーションがインストールされているか確認する方法を定期手順へ組み込む場合も、初回は対話的に候補を確認します。正常時は「探している製品の発行元と版が要件に一致し、どのユーザーまたはコンピューター範囲に導入されたか説明できる」、判定不能時は「0件でも即座に未導入とはしない。表示名の違い、ユーザー範囲、32bit側、ポータブル版の順で確認する」、中止時は「曖昧な部分一致で別製品を合格にしたり、Win32_Productを定期実行してインストーラーを動かしたりしない」をそれぞれ別の結果として扱います。これにより、0件や例外を都合よく成功へ丸めず、次の担当者が同じ対象と条件で追試できます。

修正後コードの合格条件:従来型アプリはMachine/CurrentUserとRegistry64/Registry32の4経路を全件読めたことを先に確認し、DisplayName・Publisher・Version・レジストリ位置を併記します。0件はポータブル版等を除外できるまで未導入と断定せず、Storeパッケージは別の識別子で報告します。

公式情報・参考資料

インストール済みアプリの棚卸しで使うコマンド名、引数、対応環境は次のMicrosoft一次資料で確認しました。記事の確認日は2026年7月17日です。OSやモジュール更新後は、実行端末のGet-Helpと併せて再確認してください。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次