【PowerShell】エラーハンドリング(Try-Catch)を使ってみる

PowerShell

【PowerShell】エラーハンドリング(Try-Catch)を使ってみる

2018年7月3日

こんにちは!そーまんです。

今回はエラーハンドリングについて書いてみました。エラーハンドリングは PowerShell でスクリプトを書く上で非常に重要です。それでは何故エラーハンドリングが重要なのでしょうか?


エラーハンドリングは何故必要か

スクリプトを実行される中で、想定外のエラーが発生する場合があります。

例えばファイルの読み書きの場合、そもそもの話、そのファイルにアクセスできるとは 100 % 保証できないですよね。

理由として、具体的に言うとアクセス先のファイルが削除されたとか、ファイルがロックされたとか、ネットワーク遅延とか、そもそもアクセス権限が無いとかでアクセスができないような事があるわけです。

データベースに置き換えても同様で、アクセス先のテーブルが存在しないとか、DB がメンテナンス中とか、ネットワーク遅延とか、アクセス権限が無いとかになります。

このような問題でスクリプトの処理が失敗してしまった場合、スクリプトの処理を中断しなければなりませんよね。

こういった場合にエラーハンドリングを使ってエラーメッセージや警告を表示させたり処理を中断させたりする事ができます。

ここでは、こういったエラーが出た場合のスクリプトにおけるエラーの種類として、まずは 2 種類のパターンがある事から説明して、本題の Try-Catch の説明をします。Try-Catch をすぐ見たい方は飛ばして構いません。


エラーの種類

Termination Error

エラーが発生した場合は処理を中断します。

原因としては、構文のエラーか、メモリの容量が足りないといったような場合になります。Terminating Error はエラーハンドリングで取得されます。


Non-Terminating Error

エラーは発生しますが、PowerShell は処理を継続します。これはエラーハンドリングでは取得できません。スクリプトで発生する多くのエラーは大体 Non-Terminating Error のほうだと言われています。エラーは発生するけれども、処理は継続するというパターンです。

サンプルを見てみましょう。これは人事の DB で使う更新スクリプトになります。日本の中~大企業ですと、4 月と 10 月に大規模な人事異動があると思います。

人事部はそれに合わせて人事部で持っている DB を更新しなければなりません。誰が退職したとか、入社したとか、違う部署に異動したとかです。ここでは実際 DB がないので動作はしませんが、内容は掴めると思います。


このスクリプトですが、もしファイル (CompanyEmployees.txt) が所定の場所に存在しなかったらどうなるでしょうか、またはファイルがロックされていたらどうなるでしょうか、またはアクセス権限が無い場合はどうなるでしょうか。

ファイルが見つからなかったり、ファイルの中が見れなかったりするのでエラーは発生しますが、処理は継続しています。これが Non-Terminating Error です。


では、以下のスクリプトを見てみましょう。現在 4 名従業員がいるとして、更新分の従業員のファイルと比較するとします。

実行結果を見てもらえれば分かりますが、ファイルが見つからないのですが、現在分の従業員が削除されてしまいました。

ファイルが見つかりエラーは出力されますが、処理は継続しますので削除処理をしてしまいます。


こうなってしまうと、DB から削除された従業員は DB から復旧しなければなりませんので、それなりに大ごとになります。

至急での対応が必要とされ、バックアップしたメディアを使い、DB からリストアしたりするなどの多くの作業が必要かもしれません。ですので、これは実際はあってはならないスクリプトになります。


Non-Terminating Error の中断方法

という事で、こういう場合には処理を中断する必要がある事はお分かりいただけたかと思います。

では、Non-Terminating Error で発生したエラーを中断するにはどうしたら良いでしょうか。

-ErrorAction Stop

-ErrorAction Stop を使います。処理を中止したいところに書く事によって処理を中断する事が可能になります。

もう一つは $ErrorActionPreference を使います。


$ErrorActionPreference

これは PowerShell の変数で、これを使うと全てのコマンドレットで発生したエラーを取得してどのように動作するか指定できます。

スクリプト単位で使用されるので、個々のコマンドでは使えません。その場合は ErrorAction パラメーターを使います。

デフォルトの動作は、 $ErrorActionPreference で定義されています。

通常は Continue のため、エラーをキャッチせず、処理をそのまま続行します。これを変更する場合は、Stop などをこの変数に代入します。

動作説明補足
Continueエラーを表示しますが、可能な場合は次の処理を続ける。デフォルトの動作になります。
SilentlyContinueエラーを無視します。コンソールにはエラーが表示されません。 
Stopエラーを表示し、スクリプトを中断します。 
Inquireエラーに対しての動作をユーザーに聞いてきます。処理を継続するか中断するかを聞いてきます。
$ErrorActionPreference で指定できる動作一覧


それでは、実際に Stop を指定して使ってみましょう。結果は -ErrorAction Stop と同じです。

$ErrorActionPreference = "Inquire" の場合はポップアップが表示され、エラーに対しての動作を選択するように聞いてきます。


Try Catch を使う

それではここから本題となります。Try Catch を使い、エラーハンドリングをします。

try -> catch -> finally の順で処理されます。

まずは try で処理をして、エラーが発生したら catch で処理をして、finally は省略可能ですが、エラーの有無関係なく、最後に行う処理です。構文としては以下になります。


では、実際にどんな処理ができるのか、サンプルを見てみましょう。とりあえず finally は省略して try と catch だけで書いています。

では、もう少し実践的なものを書いてみましょう。

こんな感じで書いてゆきます。なかなか慣れないと難しいですね。


まとめ

いかがでしょうか。

エラーハンドリングを使う事によって、想定外のエラーに対応する事ができ、実行されてはならない処理を防止する事ができます。

ですので、スクリプトを書く時にはエラーハンドリングが必要かどうかよく考えて、必要であればどこでどのように処理させるか考えて書くようにすれば良いでしょう。

では最後までお読みいただきありがとうございました!

  • この記事を書いた人

そーまん

セキュリティエンジニアやってます。
ブログ歴3年。PVは月15万PV程度。
趣味はボクシング、筋トレ、登山です。
穏やかで人見知りな性格です。

人気記事

1

こんにちは!そーまんです。 今回は、PC に適用されている GPO を確認する方法について書きました。 本題に入る前に、一応参考までにGPOの適用タイミングについての記事をここに貼りましたので、必要に ...

2

こんにちは!そーまんです。 今回は sysprep について、全体的に PC をセットアップする観点から書いてみました。長々と書いてあります。まずは前置きからです。 まずはじめに 組織では PC のラ ...

3

こんにちは!そーまんです。 今回は、グループポリシー (GPO) を使って、特定のコンピューターに対して、ドメインユーザーに ローカル管理者権限 (以下は特権と記載) を付与する方法について書きました ...

4

こんにちは!そーまんです。 今回は、Windows サインイン後に一時ユーザープロファイルが読み込まれてしまった場合の解決方法について書きました。 Windows 10 の検証環境をいじってたらサイン ...

5

こんにちは!そーまんです。 今回は、ユーザープロファイルを削除する方法について書いてみました。 企業の場合よくあることですが、1 台の PC を共有 PC として複数人で使ったり、また余り無いかもしれ ...

6

こんにちは!SE ブログの相馬です。       今回は、繰り返し文について書いてみました。PowerShell では他のプログラミング言語同様、繰り返し処理を行うことが ...

7

コマンドを使って CPU とメモリの使用率をデータで取得してみましたので、例えば PC のトラブルシューティングで問題を再現させる際にデータを取得しておくと、原因の特定に役立つ場合があるかと思います。

8

既存の PC と同じ構成で別のメーカーの PC でマスターイメージを作る際、インストールされているアプリを同一にする為に必要になるかと思います。

9

企業で多くの GPO が適用されている環境では、PC に GPO が適用されなかったりする問題が発生する場合があるかと思います。その中でも、コンピューターの構成またはユーザーの構成のどちらかで、...

10

こんにちは!そーまんです。 今回は、Windows Server 2019 で NTP サーバーと同期する方法について書きました。 NTP サーバーの必要性や時刻同期の重要性を理解することは社内のシス ...

-PowerShell
-