VPN のウィンドウを開いてから十秒眠るスクリプトは推測であり、その推測は両方向に間違っている:トンネルが使える前にコピーを始めるか、作業を始められたはずの後に待つかだ。どちらの結果も認証が終わったかどうかを教えない。コマンド自身の結果を使い、その後にサービスへ実際に答えられる質問を投げる。この二つの手順の順序が設計のすべてだ。

コマンドが実際に何を報告するか

インストールされたコマンドラインツールが理解するネイティブの Windows プロファイルでは、rasdial.exe が名前付きエントリをダイヤルし、プロセスの終了コードを返す。そのコードはダイヤルの試行を表す:ゼロはそのプロファイルの接続が確立したことを意味し、非ゼロはコードが示す段階で失敗したことを意味する。これは一つの層の結果として読み、ジョブの結果として読まない。

結果はアドレスの割り当て、プライベート DNS、追加されたルート、特定のサーバーへの到達許可については何も語らない。これらはすべてダイヤル成功の後に起こり、どれもまだ間違っている可能性がある。接続済みアイコンと失敗したコピーがこれほど頻繁に同居するのは、この隙間のためだ。

ほかの何かが動く前に結果を記録する

まず、テストに使うアカウントだけでなく、ジョブを実行するアカウントにプロファイルが存在することを確認する:

Get-VpnConnection -Name "Contoso-Office"
Get-VpnConnection -Name "Contoso-Office" -AllUserConnection

次にダイヤルし、すぐにコードを読む。PowerShell がネイティブの結果を $LASTEXITCODE に保持するのは次の外部コマンドが走るまでで、ダイヤルと確認の間にはさまった ping は読むつもりの値を壊す。まず自分の変数へ代入してから、どうするかを決める。

& rasdial.exe "Contoso-Office"
$dial = $LASTEXITCODE
if ($dial -ne 0) { throw "rasdial failed with $dial" }

コードは秘密でないエラー文言と一緒に記録する:エントリの欠落、拒否された資格情報、タイムアウトでは対応が異なるからだ。表はよくある結果を次の行動に結びつける。

ResultWhat it indicatesNext step
0The dial completedProbe the resource, do not start writing yet
691The credential or authentication method was rejectedFix the account or method, do not retry in a loop
623The named entry was not foundFix the profile name or its scope
Other non-zeroTransport, timeout or adapter failureRead the message, then check the path

準備ができているのはトンネルではなくリソースだ

ダイヤルが成功したら、ジョブが必要とするものを試す。共有、API のエンドポイント、データベースのポートは、機能しているどの経路からも応答してプライベートな経路については何も証明しない公開ウェブサイトより良い準備確認だ。アプリケーション自身が依存する確認を選ぶ。TCP 接続の成功はルーティングとフィルタリングが開いていることを示し、最初の書き込みに必要なものの大半はこれだ:

Test-NetConnection -ComputerName files.contoso.example -Port 445

試行回数を区切り、どの段階で失敗したかを記録する。拒否された資格情報はスクリプトを止めるべきで、再試行ループに餌を与えるべきではなく、まだ現れない DNS 名には短い再試行を数回、決して開かないポートはクライアントより上流のルーティングかポリシーの問題だ。

ジョブの開始前から接続が存在していた場合は、そのままにしておく。自分が開いていないセッションを切断すると利用者の別の作業を中断させるので、セッションの所有者と適切な後始末を記録する。

プロファイルをジョブを実行するアカウントに限定する

スケジュールされたタスクは独自の ID とセッションで動くので、デスクトップで動くプロファイルがそこでは見えないことがある。スケジュールを信じる前に、可視性の確認とダイヤルをタスクのアカウントでやり直す。パスワードもコマンドラインから外す:引数は他のプロセスから見え、しばしばログに残る。

展開にブラウザーのプロンプト、スマートカードのタッチ、MFA の承認が必要なら、そのやり取りは設計の一部であり、キー入力を模擬して自動化することはできない。その場合はサポートされたクライアントを使い、人間の手順をそのまま行う。

最終的なスクリプトの形は短いままだ:プロファイルを確認し、ダイヤルし、コードを読み、リソースを試し、それから作業を始める。各手順は前の手順が答えられなかった問いに答えるもので、どれもスリープに頼らない。

関連記事