Windows には VPN クライアント向けの再接続ポリシーがないため、真夜中に切れた接続は朝食時にも切れたままです。切断を監視して rasdial を実行するスケジュール タスクなら、サードパーティのクライアントなしでその隙間を埋められます。タスクが運用者のように振る舞うかループのように振る舞うかは、三つの点——どのイベントに一致させるか、どの資格情報を参照できるか、結果をどう扱うか——にかかっています。三つのどれも難しくはなく、どれか一つでも欠けると永久にダイヤルするタスクになります。

タイマーが誤ったトリガーである理由

タイマーはトンネルが切れていてもいなくても、独自のスケジュールでダイヤルします。それでは誰も必要としない試行が生まれ、作業セッション中の試行はそのセッションを中断させることがあります。イベント トリガーは接続の状態が変わったときだけ発火するので、安価で考えやすくなります。イベントは理由も運び、その理由こそがネットワーク障害と意図的な切断を分けるものです。

その区別が、役に立つタスクと毎晩ユーザーと戦うタスクの違いです。また、アクションだけを説明するレシピにたいてい欠けている部分でもあります。

イベントのペアと、抑止すべきもの

Remote Access Service クライアントは、RasClient プロバイダーの下で Application ログにライフサイクル レコードを書き込みます。20226 は終了した接続を、20227 は失敗した試行を示すので、どちらも新しいダイヤルを正当化できます。タスクの他のすべては、この二つの識別子を正確に一致させることにかかっています。これらは何年も安定しているため、それに基づくレシピはいまも流通していますが、プロバイダーや ID の名前を変えるビルドではクエリが何も返さなくなります。機能の更新のたびに、タスクが発火しなくなるのを待つのではなく、証明の手順をやり直してください。

除外すべき終了が一つあります。エラー 631 はユーザーがポートを切断したことを意味し、その瞬間の再ダイヤルは、たったいま意図的にネットワークを切り替えた人と戦うことになります。除外は、タスクがそもそも開始されないように、スクリプトではなくトリガーのフィルターに置いてください。これは一つのイベント ID にだけ適用する必要があります——EventData 述語は指定した要素が存在するときだけ一致するため、共通の条件節はもう一方の ID のイベントをすべて黙って落としてしまうからです。フィルターを書く前に、実際のレコードから要素名を読み取ってください:

Get-WinEvent -LogName Application -MaxEvents 5 -FilterXPath "*[System[Provider[@Name='RasClient'] and EventID=20226]]" | Select-Object -First 1 -ExpandProperty ToXml

XML はそのレコード内の Data の正確な名前を示します。ErrorCode が通常の綴りで、別のものを使うレコードでは下のフィルターでその名前に置き換える必要があります。

<QueryList><Query Id="0" Path="Application"><Select Path="Application">*[System[Provider[@Name='RasClient'] and (EventID=20226 or EventID=20227)]] and (EventData[Data[@Name='ErrorCode'] != '631'] or System[EventID=20227])</Select></Query></QueryList>

それをトリガーのカスタム フィルターに貼り付け、トリガーになる前にクエリとして証明してください。同じ XPath を PowerShell から実際のログに対して実行でき、タスク履歴がまだ関与していないうちに何に一致するかを安く確認できます。

Get-WinEvent -LogName Application -MaxEvents 40 -FilterXPath "*[System[Provider[@Name='RasClient'] and (EventID=20226 or EventID=20227)]] and (EventData[Data[@Name='ErrorCode'] != '631'] or System[EventID=20227])" | Select-Object TimeCreated,Id,Message

何にも一致しないトリガーは、実行されて失敗するタスクとまったく同じに見えます。どちらも「自動化が動かない」という形で現れ、どちらの半分が欠けているかは語りません。まずクエリの出力を確認してください——二つのケースを一手で切り分けられます。

パスワードを入力する人がいないためにダイヤルが失敗する

アクションは接続名を付けて rasdial を実行します。プロファイルにキャッシュされた資格情報がない場合、プロンプトに答える人がいないためダイヤルはすぐに失敗します。正しくトリガーされたタスクが何も見える動作をしない最も一般的な理由はこれなので、トリガーに触る前に確認してください。コマンド プロンプトから手動でダイヤルすれば、資格情報の問題とスケジュールの問題を切り分けられます。

資格情報は、タスクを実行するアカウントの下で一度保存し、そのアカウントを設計の一部にしてください。SYSTEM として実行されるタスクは、対話型アカウントがキャッシュした資格情報を読めませんし、別のユーザーとして実行されるタスクも読めません。名前は、ユーザー フィールドのドメイン プレフィックスも含めて、プロファイルと正確に一致する必要があります。

rasdial
rasdial "Office VPN"
(Start-Process rasdial -ArgumentList '"Office VPN"' -Wait -PassThru -NoNewWindow).ExitCode

最初のコマンドは Windows が認識している名前を一覧表示します。二番目はキャッシュされた資格情報を使って名前でダイヤルし、三番目は PowerShell アクションが使うべき形式で、待機して、タスクが記録できる値を返すからです。

ウィンドウではなく終了コードを読む

待たずにプロセスを起動するタスクは、プロセスが存在した時点で成功を報告します。一秒後に失敗しうるダイヤルにとって、その判定は無価値です。終了コードを待つことで、アクションは本当の結果になります。タスク履歴だけではプロセスが起動したことしか分からず、トンネルが上がったことは決して分かりません。

実行のたびにタイムスタンプ付きで値を記録してください。障害後の一度の失敗は正常ですが、同じコードで三回連続して失敗する場合は、ネットワークではなく資格情報かプロファイルを示します。そのパターンがあってこそ、履歴は読む価値を持ちます。

保険として短い繰り返し間隔を追加し、イベント トリガーとどう相互作用するかを明示してください。五分間のあいだ毎分繰り返せば、インターネットがトンネルとともに戻ってきたときに二回目の試行を供給し、設定の「タスクが既に実行中の場合、次の規則を適用する」では、繰り返しが進行中のダイヤルと重ならないように「新しいインスタンスを開始しない」を選ぶべきです。その設定がないと、二つの rasdial プロセスが同じポートを奪い合い、二番目は有益な理由もなく失敗します。

復旧経路を証明する

両方向を意図的に試してください。手動で切断して再ダイヤルが起きないことを確認し、次にネットワーク アダプターを無効にして、リンクが戻ったときにタスクが発火することを確認します。この二つのテストが抑止ルールと実際の障害ケースを覆い、ほかの何もそれをしません。

そのあとは接続アイコンではなくタスク履歴を読んでください。履歴には、タスクがいつ実行され、どのアカウントを使い、アクションが何を返したかが記録され、来月同じマシンが再び落ちたときに必要になる証拠はそれです。

関連記事