PowerShellでUSBデバイスの接続履歴を確認する方法

PowerShellでUSBデバイスの接続履歴を確認する方法という問いには、現在のInstanceIdを取得し、対応文字列をSetupAPIデバイス導入ログと利用可能なイベントログで照合するという方法で答えます。Get-PnpDeviceは現在または登録済みデバイスを示すが、完全な接続履歴台帳ではない。setupapi.dev.logはデバイス導入処理を記録するため、抜き差しの全時刻や操作ユーザーを必ず証明するものではない。この記事ではUSB InstanceId、VID、PID、Serial相当部分、SetupAPIセクション開始時刻を相互に照合するを判断軸にし、実行前の確認、記事固有のコード、合否判定、戻し方を一続きで示します。

seq22の現在接続一覧ではなく、導入ログに残る過去の痕跡と限界を説明する。完了は「対象InstanceIdに対応する導入セクションと時刻を示し、現在接続・過去導入・推定を別々に報告できる」と定義します。対象が取れない場合は「ログに該当がなければ保存期間、ログ更新、別InstanceId、USBハブ配下を確認し、未接続だったと断定しない」として切り分け、推測で成功扱いにしません。

目次

現在接続と過去導入を区別

現在接続と過去導入を区別では、USBデバイスの接続履歴調査の対象を「USB InstanceId、VID、PID、Serial相当部分、SetupAPIセクション開始時刻を相互に照合する」という単位で扱います。Get-PnpDeviceは現在または登録済みデバイスを示すが、完全な接続履歴台帳ではない。setupapi.dev.logはデバイス導入処理を記録するため、抜き差しの全時刻や操作ユーザーを必ず証明するものではない。対象が複数なら表示名の部分一致で先頭を採らず、一意になる条件を追加します。

USBデバイスの接続履歴調査を始める前に、PowerShellの版、コマンドの提供元、必要権限、管理ポリシーの有無を確認します。権限不足と対象なしは意味が異なるため、例外を0件へ置き換えません。

InstanceIdからVIDとPIDを特定

InstanceIdからVIDとPIDを特定は変更前の基準点です。USB InstanceId、VID、PID、Serial相当部分、SetupAPIセクション開始時刻を相互に照合するを出力に含め、取得時刻と一緒に保存します。値だけを切り取ると別対象との比較になるため、識別列を省きません。

$instanceId = 'USB\VID_1234&PID_5678\SERIAL123'
$current = @(Get-PnpDevice -PresentOnly -ErrorAction Stop |
  Where-Object InstanceId -eq $instanceId)
if ($current.Count -gt 1) { throw '現在デバイスを一意にできません。' }
[pscustomobject]@{
  InstanceId=$instanceId; PresentNow=($current.Count -eq 1)
  FriendlyName=if ($current.Count) { $current[0].FriendlyName } else { $null }
  Status=if ($current.Count) { $current[0].Status } else { $null }
}

Get-PnpDeviceは現在または登録済みデバイスを示すが、完全な接続履歴台帳ではない。setupapi.dev.logはデバイス導入処理を記録するため、抜き差しの全時刻や操作ユーザーを必ず証明するものではない。出力が多い場合も最初から無理に一件へ絞らず、候補数と除外理由を残してから対象を決めます。

SetupAPIデバイス導入ログを検索

現在のInstanceIdを取得し、対応文字列をSetupAPIデバイス導入ログと利用可能なイベントログで照合する。USBデバイスの接続履歴調査ではこの進め方により、操作したという事実ではなく、期待する状態へ到達したかでタイトルの問いへ答えられます。seq22の現在接続一覧ではなく、導入ログに残る過去の痕跡と限界を説明する。

SetupAPIデバイス導入ログを検索の合格条件は、対象InstanceIdに対応する導入セクションと時刻を示し、現在接続・過去導入・推定を別々に報告できることです。作業時刻、実行ユーザー、端末名を添え、判断に使った値が後から追える形にします。

イベントログは有効な範囲だけ使う

イベントログは有効な範囲だけ使うでは、現在のInstanceIdを取得し、対応文字列をSetupAPIデバイス導入ログと利用可能なイベントログで照合する。USBデバイスの接続履歴調査の例中にある名前、パス、ID、時刻はサンプルなので、そのまま本番へ貼らず、直前の読み取り結果から承認値を入れます。

$setupLog = Join-Path $env:WINDIR 'INF\setupapi.dev.log'
$evidenceCopy = Join-Path $env:TEMP ("setupapi.dev-{0}.log" -f ([guid]::NewGuid().ToString('N')))
if (Test-Path -LiteralPath $evidenceCopy) { throw "証拠コピーを上書きしません: $evidenceCopy" }
$sourceHash = Get-FileHash -LiteralPath $setupLog -Algorithm SHA256
Copy-Item -LiteralPath $setupLog -Destination $evidenceCopy -ErrorAction Stop
$copyHash = Get-FileHash -LiteralPath $evidenceCopy -Algorithm SHA256
if ($copyHash.Hash -ne $sourceHash.Hash) { throw 'SetupAPI調査コピーのSHA256が一致しません。' }
$text = Get-Content -LiteralPath $evidenceCopy -Raw -ErrorAction Stop
$pattern = '(?ms)^>>>\s+\[(?<header>[^\r\n]+)\]\r?\n(?<body>.*?)^<<<\s+\[Exit status:\s*(?<status>[^\]]+)\]'
$sections = @([regex]::Matches($text, $pattern) | Where-Object {
  $_.Value.IndexOf($instanceId, [StringComparison]::OrdinalIgnoreCase) -ge 0
})
$installRows = @($sections | ForEach-Object {
  $start = [regex]::Match($_.Groups['body'].Value, '(?m)^>>>\s+Section start\s+(?<stamp>.+)$')
  [pscustomobject]@{
    InstanceId=$instanceId; SectionHeader=$_.Groups['header'].Value
    SectionStart=if ($start.Success) { $start.Groups['stamp'].Value.Trim() } else { $null }
    ExitStatus=$_.Groups['status'].Value.Trim()
    EvidenceSha256=$copyHash.Hash
  }
})
if ($installRows.Count -eq 0) {
  Write-Warning '対象InstanceIdのSetupAPI導入セクションは保存範囲内で見つかりません。'
}

ログの時刻だけで特定ユーザーの操作と断定しない。調査対象ログへ書き込みや整形を加えない。USBデバイスの接続履歴調査でプレビュー対応コマンドを使える場合はWhatIfを先に実行し、非対応の操作は対象一覧と引数を画面へ出して人が承認してから一度だけ実行します。

時刻とユーザーを断定しすぎない

時刻とユーザーを断定しすぎないでは同じ対象を別経路でもう一度読みます。判定したいのは「コマンドが終了したか」ではなく、対象InstanceIdに対応する導入セクションと時刻を示し、現在接続・過去導入・推定を別々に報告できるかどうかです。

$events = @(Get-WinEvent -FilterHashtable @{
  LogName='System'; ProviderName='Microsoft-Windows-Kernel-PnP'
  StartTime=(Get-Date).AddDays(-7)
} -ErrorAction SilentlyContinue | Where-Object {
  $_.Message -and $_.Message.IndexOf($instanceId, [StringComparison]::OrdinalIgnoreCase) -ge 0
} | Select-Object TimeCreated, Id, ProviderName, Message)
[pscustomobject]@{
  InstanceId=$instanceId; PresentNow=($current.Count -eq 1)
  SetupInstallSectionCount=$installRows.Count
  AuxiliaryEventCount=$events.Count
  UserAttribution='NotEstablished'
}
$installRows | Format-Table SectionStart, ExitStatus, SectionHeader
$events | Select-Object -First 20

ログに該当がなければ保存期間、ログ更新、別InstanceId、USBハブ配下を確認し、未接続だったと断定しない。USBデバイスの接続履歴調査の期待値と実測値が一致しないときは追加変更を重ねず、対象識別、権限、ポリシー、時間差の順で原因を分けます。

ログがローテーション済みの場合

ログの時刻だけで特定ユーザーの操作と断定しない。調査対象ログへ書き込みや整形を加えない。ログがローテーション済みの場合に該当したら、警告を消して継続するのではなく、どの条件で止まったかを記録します。

ログに該当がなければ保存期間、ログ更新、別InstanceId、USBハブ配下を確認し、未接続だったと断定しない。USBデバイスの接続履歴調査ではエラー本文、FullyQualifiedErrorId、対象ID、直前に成功した段階を残すと、別担当者が安全な地点から調査できます。

証拠ファイルを変更せず保全

資産管理目的なら将来の監査ログ設計を別途用意し、後からSetupAPIだけで完全履歴を再現できると期待しない。USBデバイスの接続履歴調査を繰り返す場合は、正常、対象なし、要承認、失敗を異なる終了状態として記録し、前回値との比較だけで異常を決めません。

証拠ファイルを変更せず保全の識別軸USB InstanceId、VID、PID、Serial相当部分、SetupAPIセクション開始時刻を相互に照合する
採用する実測対象InstanceIdに対応する導入セクションと時刻を示し、現在接続・過去導入・推定を別々に報告できる
0件時の扱いログに該当がなければ保存期間、ログ更新、別InstanceId、USBハブ配下を確認し、未接続だったと断定しない
保留にする兆候ログの時刻だけで特定ユーザーの操作と断定しない。調査対象ログへ書き込みや整形を加えない

USBデバイスの接続履歴調査の実行記録には、開始前の対象候補、採用した識別値、実行したコード、終了後の実測、除外した候補と理由を同じ作業番号で残します。特に「USB InstanceId、VID、PID、Serial相当部分、SetupAPIセクション開始時刻を相互に照合する」を省くと、後日の再確認で別対象の値を比較するおそれがあります。画面コピーだけでなく、日時と端末名を含む構造化した出力も保存します。

PowerShellでUSBデバイスの接続履歴を確認する方法を定期手順へ組み込む場合も、初回は対話的に候補を確認します。正常時は「対象InstanceIdに対応する導入セクションと時刻を示し、現在接続・過去導入・推定を別々に報告できる」、判定不能時は「ログに該当がなければ保存期間、ログ更新、別InstanceId、USBハブ配下を確認し、未接続だったと断定しない」、中止時は「ログの時刻だけで特定ユーザーの操作と断定しない。調査対象ログへ書き込みや整形を加えない」をそれぞれ別の結果として扱います。これにより、0件や例外を都合よく成功へ丸めず、次の担当者が同じ対象と条件で追試できます。

修正後コードの合格条件:現在のPnP状態、SetupAPIの過去導入セクション、補助イベントを別列で報告します。SetupAPIコピーのSHA256を原本と一致させ、対象InstanceIdを含むセクションのSection startとExit statusが取れたときだけ過去導入の証拠とします。

公式情報・参考資料

USBデバイスの接続履歴調査で使うコマンド名、引数、対応環境は次のMicrosoft一次資料で確認しました。記事の確認日は2026年7月17日です。OSやモジュール更新後は、実行端末のGet-Helpと併せて再確認してください。

この記事を書いた人

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

コメント

コメントする

目次