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

ソースコードはこちらで公開しています。

https://github.com/iwadjp/task-scheduler-diagnostic