PowerShellを使ってアプリケーションの異常終了を報告する方法の手順を先に要約すると「異常終了の報告はprocess不在判定ではなく、Get-WinEventでApplication ErrorやWindows Error Reportingのeventを取得し、時刻、event ID、application version、fault module、例外codeを最小限に記録します。」となります。対象環境はprocessが見つからないことをcrashと断定せず、Application ErrorやWER eventを時刻・process・fault moduleで確認する構成です。
調査時間窓と対象applicationを固定する
アプリクラッシュ調査では、対象実行ファイル名と発生時間帯を固定し、Application ErrorやWindows Error ReportingのRecordId、Provider、Event ID、XMLフィールドを取得します。同じ障害を時刻だけで結び付けず、Faulting Application、Module、Report IDを照合し、重複イベントを一件に集約します。
- 対象applicationの正式exe名とversionを確認する
- crash発生時刻とtimezone、user操作を記録する
- Application logのProviderNameとevent IDを確認する
- dumpやreportに個人情報が含まれるため保存先を確認する
Application Error 1000をserver側で絞る
event取得は読み取りです。旧Send-MailMessageは新規設計の既定にせず、組織の承認済みnotification基盤へ最小reportを送ります。SMTP credentialをscriptへ記載しません。dumpにはmemory上のsecretが含まれるため、収集範囲、暗号化、ACL、保持期限をincident手順に従います。crash原因調査中にsecurity設定を無効化しません。
WER eventを近接時刻で補足する
Application Errorを期間検索
$start=(Get-Date).AddHours(-2)
Get-WinEvent -FilterHashtable @{LogName='Application';ProviderName='Application Error';Id=1000;StartTime=$start} -MaxEvents 100 |
Select-Object TimeCreated,RecordId,Id,Message
IDとproviderを組にします。messageから必要項目だけ抽出します。
WER eventを補足
Get-WinEvent -FilterHashtable @{LogName='Application';ProviderName='Windows Error Reporting';StartTime=$start} -MaxEvents 100 |
Select-Object TimeCreated,Id,RecordId,Message
同時刻のApplication Errorと相関します。
process不在を別状態で扱う
$p=Get-Process -Name 'notepad' -ErrorAction SilentlyContinue
if($p){$p | Select-Object Id,StartTime,Path}else{'NotRunningAtCheckTime'}
NotRunningAtCheckTimeはcrash証拠ではありません。正常終了や未起動も含みます。
report objectを作る
$event=Get-WinEvent -FilterHashtable @{LogName='Application';ProviderName='Application Error';Id=1000} -MaxEvents 1
[pscustomobject]@{Host=$env:COMPUTERNAME;Time=$event.TimeCreated;RecordId=$event.RecordId;EventId=$event.Id} | Export-Csv '.\crash-summary.csv' -NoTypeInformation
message全文やuser dataを既定で含めません。
crash対象EXEの署名を確認
Get-AuthenticodeSignature -LiteralPath 'C:\Program Files\Target\target.exe' | Select-Object Status,SignerCertificate
対象pathはeventとinventoryから確認します。
現在のprocess状態を過去crashと分ける
process不在は異常終了、正常終了、未起動、別user sessionのいずれでも起こります。event ID 1000はcrashの手掛かりで、faulting moduleやexception codeをvendor資料と照合します。同一crashから複数eventが生成される場合があり、件数はRecordIdと時刻でdeduplicateします。
event XMLから必要項目だけ保存する
- process不在をcrashと断定する
- event IDだけ見てproviderを無視する
- Message全文をmailする
- credentialをscriptへ埋め込む
- 複数eventを別crashとして数える
dump設定変更を収集手順から切り離す
Event Viewer、WER history、application log、監視alertの時刻とversionを照合します。正常終了、未起動、実crashをtest環境で区別し、reportが必要項目だけを持つことをreviewします。通知失敗でもevidenceを失わず再送可能にします。
RecordId・時刻・process identityを検収する
Application Error event 1000とWindows Error Reporting eventをTimeCreated、faulting application、module、exception code、report IDで相関します。process不在はcrash後の通常状態になり得るため、event 0件・process終了・取得errorを別にします。
Application Error eventを上限付きで収集する
$start=(Get-Date).AddHours(-2)
$events=@(Get-WinEvent -FilterHashtable @{LogName='Application';ProviderName='Application Error';Id=1000;StartTime=$start} -MaxEvents 100 -ErrorAction Stop)
$events | Select-Object TimeCreated,RecordId,Id,ProviderName,@{n='Xml';e={$_.ToXml()}}
crash eventの有無をquery成否と独立評価する
- crash event取得:指定期間のeventからRecordIdとXML fieldを取得し、同一crash候補を時刻/名前/report IDで対応付ける
- 期間内crashなし:event 0件は調査期間内に記録なしとして扱い、crash否定にはしない
- event・signature error:log access、event schema差、missing executable、signature errorはEvidenceGapとして残す
localized Messageのregexだけでfieldを抽出せずToXmlのData名を確認します。WER archiveにはdumpや個人情報が含まれ得るため、本文を広くcopyせず最小metadataに限定します。
process不在と複数crashを試す
$p=Get-Process -Name 'notepad' -ErrorAction SilentlyContinue
[pscustomobject]@{ProcessState=if($p){'Running'}else{'NotRunning'};CrashEvents=$events.Count;WindowStart=$start}
event 0/1/複数、same-name process、schema欠損、unsigned exeをtestします。host/timezone、RecordId、event XML field、exe hash/signature、相関ruleを保存します。
現在processが動いていることは、時間窓内にcrashがなかった証拠ではありません。Application ErrorとWERを時刻・実行file・faulting moduleで相関し、dump収集の有効化は別承認にします。

コメント