PowerShell は、その名前が示すように、標準の Windows コマンド プロンプトよりもはるかに強力です。 そのパワーは、紛らわしいエラーの可能性をより大きくします。 スクリプトが突然失敗した場合、何が問題だったのかを探すためにどこから始めればよいのかわからないかもしれません。 そこで、PowerShellのエラーハンドリングが役に立ちます。
もしあなたが他の言語に精通しているなら、おそらくエラー処理の基本をご存知でしょうが、PowerShellに特有のいくつかの側面も知っておく必要があります。 PowerShellのエラー処理には、Error Actionパラメータ、Try/Catchブロック、Error Variableパラメータ、ロギングの4つの部分があります。
PowerShell エラー処理の簡単な方法
PowerShell エラー処理の最初のステップは、スクリプトを停止させるものに対処することです。 その失敗がスクリプトの残りの部分に影響しない場合、エラーを無視して先に進むように PowerShell に指示するのが最善かもしれません。
一方、特定のコマンドレットが終了エラーを投げるとき、常に明確であるとは限りません。 いくつかのコマンドレットは、エラーを返しますが、スクリプトを停止しません。 これは、無意味な出力をしながらスクリプトの完了を待つことになりかねません。
そこで、-ErrorAction パラメーターの出番です。 これを使用して、コマンドレットが希望する方法でエラーを処理するように強制します。 既存のスクリプトを変更する場合は、コマンドレット行の最後にこのパラメータを追加します。
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Stop
明らかに、Get-ChildItem コマンドレットをそれ自体で使用する場合、このエラーはあまり役に立ちません。 しかし、データに対して何かを行いたい場合、スクリプトを停止し、検索が失敗したこととその理由を知ることは良いことでしょう。 あるいは、複数の検索を行う場合は、パラメータを Stop から SilentlyContinue に変更し、検索に失敗してもスクリプトは続行するようにする。 エラーの内容を確認したい場合は、代わりにContinueをパラメータとして使用します。
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction SilentlyContinue
スクリプトを実行するたびに何が起こるかを制御するオプションが必要な場合は、Inquireに変更できます。 このコマンドレットは、問題が発生したときに、オプションを提供します。 Yes、Yes For All、Halt Command、Suspend、またはHelpのオプションがあります。
このオプションはもう少し柔軟ですが、エラーが発生するとスクリプトが入力待ちの状態になることを意味します。 PowerShell を使用して電子メールを送信するなどの簡単なタスクであれば問題ありませんが、長いプロセスを夜間に実行する場合は望ましくありません。
PowerShell エラー処理の強力な方法
ErrorAction パラメータは、単純な方法でエラーに対処します。 しかし、エラーに対してもう少し制御したい場合、PowerShell はまだあなたをカバーしています。 Try/Catch を使用すると、コマンドレットがエラーを返したときにスクリプトを分岐させることができるようになりました。
名前が示すように、Try/Catch は 2 つの部分から構成されています。 (技術的には 3 番目がありますが、それについては後ほど説明します。) 1 番目は Try セクションです。 このセクションで通常のコードを実行することになります。 ErrorAction パラメータは引き続き使用しますが、Stop としてのみ設定できます。 このフラグは、コマンドレットが終了エラーを持っていない場合でも、Catch—をトリガーすることを保証します。
Try{
Get-Process "Cortana" -ErrorAction Stop
}
Try は、検索が失敗した場合に他のコマンドレットが実行されるのを防ぐこともできます。 この場合、Get-Processの結果をStop-Processに送信していた場合、検索に失敗すると2番目のコマンドレットが実行できなくなります。
さて、コマンドレットのトライブロックを作成しましたが、失敗したときにどうしたいですか? Catchハーフを使って、このように定義することになります。
Catch{
Write-Host "Process Not Found"
}
ErrorAction パラメーターと同様に、もう少し複雑なことを行っているときは、特に、わかりやすい失敗を与える以外にも Catch は有用でしょう。 (上の例では、プロセス名ではなく、アプリ名を使うことで強制的に失敗させています)。 ですから、 Try ブロックで遊んで、必要な検索/アクションを作成するようにしてください。 Catchブロックを使って、失敗したときにメールを送るスクリプトを作成することができます。
3 番目の部分は、コマンドレットが成功するかどうかに関係なく何かを実行したい場合に便利です。 これには、Finally ブロックを使用します。 Try と Catch の後にこれを追加し、スクリプトのセクションが終了したときにログを記録します。
エラー変数とログ
これで、スクリプトがエラーを処理する方法とエラーに応答する方法を制御できるようになりました。 スケジュールされたタスクとして使用することができ、少なくともデスクにいないときに実行することができます。 しかし、失敗したスクリプトをどのように調査すればよいのでしょうか。 ErrorVariableパラメータを使用すると、コマンドレットのエラーはカスタム変数に書き込まれます。
これは、現在のセッションのすべてのエラーを含むシステム $Error 変数の代わりとなります。
コマンドレットは少し長くなる必要があります。 まず、変数を定義します。この例では $SearchError のようなものを使用します。 ErrorVariable パラメータで SearchError を呼び出す場合、ドル記号は使用しません。
作成した変数を呼び出しているにもかかわらず、パラメータの動作方法によって、ドル記号を付けずに呼び出すのです。 そして、それを行の最後に追加します。
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Continue -ErrorVariable SearchError
変数名の前に + を追加すると、変数を完全に置き換えるのではなく、変数に追加することができます。 そうすると、グローバルエラー変数と同じ動作になります。 その代わり、この出力とTry/Catchを使用してカスタム出力を書き、タイムスタンプを押すことができます。
これを動作させるには、エラー変数を設定した後にテキスト ファイルを作成します。 New-Itemコマンドレットでこれを行います。 ErrorAction パラメータに Inquire オプションを使用するとよいでしょう。 これにより、New-Itemコマンドレットが失敗したときに、既存のログに追加することができます。
$SearchLog = New-Item "~\SearchLog.txt" -type file -ErrorAction Inquire
これで Try/Catch ブロックを構築するときに、Catch を使用してテキスト ファイルにログを記録することができます。 タイムスタンプを作成するために Get-Date を使用します。 書式は難しいので、必ず例からコピーしてください。
Try{
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Stop -ErrorVariable SearchError
}
Catch{
Add-Content -Path $SearchLog -Value "$(Get-Date -Format dd-MM-yy-hh_mm_ss) Files not found returned error: $SearchError"
}
必要に応じてこれをすべてのコマンドレットで繰り返すと、あらゆるエラーのログが作成されます。 正常に実行されたものを追跡したい場合は、Try ブロックの最後に同様の Add-Content を追加することができます。
このロギングは、Try コマンドレットが成功したときのみ実行されます。 そして、エラーと成功をタイムスタンプ付きでログに記録することができます。 このログ記録により、スクリプトが行ったすべてのこと、成功または失敗を知ることができます。
PowerShell は唯一の選択肢ではない
PowerShell は多くの Windows タスクにとって便利なツールですが、学ぶのが大変な場合もあります。 また、すべてに適しているわけではありません。 コンピュータのシステムメンテナンスをしたり、ファイルの整合性をチェックしたりするのであれば、PowerShellは便利です。 一方、インターネットからファイルをダウンロードするスクリプトを実行したり、より一般的なタスクであれば、他の選択肢もあります。
たとえば、Unix や Linux のバックグラウンドをお持ちの方は、bash シェルを使う方が快適かもしれません。 Windows Subsystem for Linux のおかげで、Windows 10 コンピューターで bash やその他の Linux ツールを簡単に使用できるようになりました。 Windows 10 で bash シェルを実行するためのガイドをご覧ください。
Kris Wouk はミュージシャン、ライター、そして誰かがウェブ用にビデオを作るときに呼ばれるものです。 また、このような状況下でも、「自分には何ができるのか」ということを考えることができるようになりました。