Windows Task Schedulerが失敗する原因を1コマンドで確認するPowerShellスクリプトを作った
Windows Task Schedulerでタスクを組んでいると、手動で実行すると正常に動くのに、スケジュール実行だと失敗する、ということがあります。原因を調べようとすると、タスクのLastTaskResultだけでは何が起きたのか分かりにくく、プロパティの各タブやEvent Viewerを何箇所も見て回る必要があります。今回、この切り分けを1コマンドで済ませるPowerShellスクリプトを作ってみました。
実際に困った例
自分の環境でも、あるスケジュールタスクのLastTaskResultが0x800710E0(「操作者または管理者が要求を拒否した」)になっているのを見つけました。タスクのプロパティを開くと、LogonTypeがInteractive(ユーザーがログインしているセッションでのみ実行できる設定)になっており、これが原因の可能性が高いと分かりました。ただ、この結論にたどり着くまでに、タスクの定義、実行履歴、Event Viewerのログを個別に確認する必要がありました。
何を自動取得するか
一度の実行で以下を自動取得します。
- LastTaskResultとタスクの状態
- 実行ユーザーとLogonType・RunLevel
- 実行ファイルと引数、作業ディレクトリ
- トリガー情報
- 関連するEvent Viewerのログ(取得できない場合は有効化コマンドを案内するだけで、自動では変更しません)
何が便利か
通常であればTask Scheduler本体の一覧、プロパティダイアログ、「操作」タブ、Event Viewerという4箇所を行き来して確認する情報を、1つのコマンドを実行するだけで集められます。
実際に見つかったprototypeバグ
作っている途中、複数の実タスクで試してみたところ、2つの実バグを見つけました。1つは成功コード(0x0)を文字列比較の桁数の違いで誤って警告扱いにしていたバグ、もう1つは環境変数を含むパス(%localappdata%など)を展開せずにチェックしていたため、実際には存在するファイルを「存在しない」と誤判定していたバグです。どちらも修正し、複数の成功タスクで問題が起きないことを確認しています。1つのタスクだけで試していたら見つからなかったバグでした。
既知コード以外は推測しない
Task Schedulerのresult codeは多いため、このスクリプトでは診断ルールを絞り込んでいます。知らないコードについては原因を推測せず、「No known diagnostic rule matched.」とだけ返します。実際に今回は0x8004EE04という未対応のコードにも当たりましたが、無理に原因をでっち上げることはしていません。
使い方
以下の1コマンドで実行できます。
powershell -ExecutionPolicy Bypass -File .\diagnose-task.ps1 -TaskName "MyBackupTask"
Limitations
- 全ての失敗原因を診断できるわけではありません(現在は約20件のresult codeと、少数のdiagnostic ruleのみ)
- Event Viewerのログが無効な環境では、その情報は取得できません
- ルールベースの判定であり、AIによる推測は使っていません
- 読み取り専用です。設定変更やタスクの実行は行いません
- 外部への通信は一切行いません
Privacy
スクリプトはローカルでのGet-ScheduledTask等の読み取りのみで動作します。収集した情報を外部に送信することはありません。
GitHub
ソースコードはこちらで公開しています。