Windows PowerShell 入門(9)-エラー編
対象読者
- Windows PowerShellでコマンドレット操作ができる方
- 何らかのプログラミング経験があればなお良い
必要環境
- Windows PowerShell
エラーをリダイレクトする
リダイレクトとは、処理を行った結果の出力先を別の場所へ変更することを意味します。
通常PowerShell上で、あるコマンドを実行してエラーが発生した場合は、コンソールウィンドウにエラーメッセージが表示されます。ここでは、このエラーをファイルに出力することを「リダイレクトする」と呼んでいます。
PowerShellでエラーをファイルにリダイレクトするには、リダイレクト演算子を使用した3つの方法があります。
2> 演算子
この演算子は、エラーの内容をファイルに出力します。出力先のファイルが既に存在する場合には上書きをします。
下記は、dirコマンドで存在しないファイルを指定した場合の例です。(「C:\Work」フォルダに「HOGE.txt」が存在しないものとします)
PS C:\Work> dir HOGE.txt
Get-ChildItem : パス 'C:\Work\HOGE.txt' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir <<<< HOGE.txt
では、このエラーをファイルにリダイレクトしてみます。
PS C:\Work> dir HOGE.txt 2>err.txt
上記のように、2>
演算子の後ろに、エラーメッセージを書き込むファイル名を記述します。
では、Get-Content
コマンドレットを使用して作成された「err.txt」ファイルの中身をみてみましょう。
PS C:\Work> Get-Content err.txt
Get-ChildItem : パス 'C:\Work\HOGE.txt' が存在しないため検出できませ
ん。
発生場所 行:1 文字:4
+ dir <<<< HOGE.txt 2>err.txt
エラーの内容がリダイレクトされていることが分かります。
2>> 演算子
この演算子は、エラーの出力先のファイルが既に存在する場合は、追記書き込みを行います。
追記されることを確認するために、出力先のファイルは先ほどと同じ「err.txt」とします。また。異なるエラーメッセージが記述されるようmkdir
コマンドに変更しました。
PS C:\Work> mkdir HO*GE 2>> err.txt
実行したら、先ほど同様Get-Content
コマンドレットで確認してみましょう。
PS C:\Work> Get-Content err.txt
Get-ChildItem : パス 'C:\Work\HOGE.txt' が存在しないため検出できませ
ん。
発生場所 行:1 文字:4
+ dir <<<< HOGE.txt 2>err.txt
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item <<<< -type directory -path $paths
エラーメッセージが追記されていることが分かります。
2>&1 演算子
この演算子を使用すると、エラーの内容を変数に書き込むことができます。
$err = mkdir HO*GE 2>&1
では、エラーの内容が変数に代入されているかを確認してみましょう。
PS C:\Work> $err
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item <<<< -type directory -path $paths
通常、変数の内容を確認してもメッセージに色がつかないのですが、2>&1
演算子を使用して代入された値は、赤色で表示されていることが分かります。
これは、変数に代入された値はエラーであることを示すErrorRecord
オブジェクトとなるからです。(Error
オブジェクトは後述します))
PS C:\Work> $err.GetType() IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True ErrorRecord System.Object
2>&1
演算子を使用する以外に-ErrorVariable
パラメータを使用しても変数にエラーを代入することが可能です。
PS C:\Work> Get-ChildItem HOGE.txt -ErrorVariable err1
Get-ChildItem : パス 'C:\Work\HOGE.txt' が存在しないため検出できませ
ん。
発生場所 行:1 文字:14
+ Get-ChildItem <<<< HOGE.txt -ErrorVariable err1
-ErrorVariable
パラメータの後ろには、エラー内容を代入するための変数を指定します。このとき、指定する変数に$
を付加してはいけないことに注意してください。
$Error
変数は、PowerShellの操作時に発生したすべてのエラーが格納されますが、この-ErrorVariable
パラメータを使用した場合は、そのとき発生したエラーの内容だけを特定の変数に代入できるという違いがあります。
ErrorRecordオブジェクト
さきほど、2>&1
演算子で代入したエラーはErrorRecord
オブジェクトとなることを説明しました。では、ErrorRecord
オブジェクトにはどのようなメンバーが備わっているかを確認したいと思います。
先ほどの変数$err
に対してGet-Member
コマンドレットを使用し、どのようなメンバーがあるかを確認してみたいと思います。
PS C:\Work> $err | Get-Member TypeName: System.Management.Automation.ErrorRecord Name MemberType Definition
---- ---------- ----------
Equals Method System.Boolean Equals(Object obj)
GetHashCode Method System.Int32 GetHashCode()
GetObjectData Method System.Void
GetObjectData(SerializationInfo info, StreamingContext context)
GetType Method System.Type GetType()
get_CategoryInfo Method
System.Management.Automation.ErrorCategoryInfo get_CategoryInfo()
get_ErrorDetails Method
System.Management.Automation.ErrorDetails get_ErrorDetails()
get_Exception Method
System.Exception get_Exception()
get_FullyQualifiedErrorId Method
System.String get_FullyQualifiedErrorId()
get_InvocationInfo Method
System.Management.Automation.InvocationInfo get_InvocationInfo()
get_TargetObject Method System.Object get_TargetObject()
set_ErrorDetails Method
System.Void set_ErrorDetails(ErrorDetails value)
ToString Method System.String ToString()
writeErrorStream NoteProperty
System.Boolean writeErrorStream=True
CategoryInfo Property
System.Management.Automation.ErrorCategoryInfo CategoryInfo {get;}
ErrorDetails Property
System.Management.Automation.ErrorDetails ErrorDetails {get;set;}
Exception Property
System.Exception Exception {get;}
FullyQualifiedErrorId Property
System.String FullyQualifiedErrorId {get;}
InvocationInfo Property
System.Management.Automation.InvocationInfo InvocationInfo {get;}
TargetObject Property System.Object TargetObject {get;}
多くのメンバーを備えていることが確認できます。これらの中から、主要なものについて説明したいと思います。
CategoryInfoプロパティ
このプロパティは文字通り、エラーの種類についての情報が格納されています。
PS C:\Work> $err.CategoryInfo Category : InvalidArgument
Activity : New-Item
Reason : ArgumentException
TargetName : C:\Work\HO*GE
TargetType : String
Categoryが「InvalidArgument」となっていることが分かります。これはdir
コマンドに対して、無効な文字が含まれたパスを指定しているためです。さらにReason(発生理由)をみると、「ArgumentException」という例外が発生したことが分かります。
Exceptionプロパティ
Exception
プロパティ自体もさまざまなメンバーを持っていますが、規定のプロパティはMessageとなっており、エラーの内容を確認することができます。
PS C:\Work> $err.Exception
パスに無効な文字が含まれています。
InvocationInfoプロパティ
このプロパティはエラーの発生場所に関する情報が格納されます。PositionMessageの欄を見ると、「1行目の34文字目でエラーが発生した」ということを確認できます。
PS C:\Work> $err.InvocationInfo MyCommand : New-Item
ScriptLineNumber : 1
OffsetInLine : -2147483648
ScriptName :
Line : param([string[]]$paths); New-Item -type directory
-path $paths
PositionMessage :
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item
<<<< -type directory -path $paths
InvocationName : New-Item
PipelineLength : 1
PipelinePosition : 1
TargetObjectプロパティ
このプロパティには、エラー発生時の操作対象オブジェクトが格納されます。ただし、すべてのエラーがこのプロパティを設定するわけではないため、Null
の場合もあります。
PS C:\Work> $err.TargetObject
C:\Work\HO*GE
このようにErrorRecord
オブジェクトには、エラーの原因を解明する上で役立つ情報が格納されています。
$Error変数
PowerShellではエラーが発生するごとに、そのエラー内容を保存している変数があります。この変数は$Error
という自動変数で、配列型となっています。
また、この変数に格納できる最大要素数は自動変数$MaximumErrorCount
で決められており、256のエラー(規定値)を保持します。
では、実際にエラーを発生させて$Error
変数がどのように変わっていくのかを見てみます。(PowerShellを立ち上げていた方は、念のため起動し直してから始めてください)
まずは、PowerShell立ち上げ時点の$Error
変数の内容を確認しておきましょう。
PS C:\Work> $Error
PS C:\Work>
この時点でエラーは発生していないので、何も格納されていません。下記のように入力して、エラーを発生させます。
PS C:\Work> dir HOGE
Get-ChildItem : パス 'C:\Work\HOGE' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir <<<< HOGE
エラーを発生させた後の$Error
変数を確認してみます。
PS C:\Work> $Error
Get-ChildItem : パス 'C:\Work\HOGE' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir <<<< HOGE
上記のように、先ほど発生した内容が格納されていることが分かります。
$Error
は配列なので、要素数の変化について確認してみます。要素数はCount
プロパティで確認することができます。
PS C:\Work> $Error.Count
1
エラーは1つしか発生していないので、要素数は"1"となります。
次に、もう1つエラーを発生させてみましょう。
PS C:\Work> mkdir HO*GE2
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item <<<< -type directory -path $paths
この状態で$Error
変数の内容を確認してみると
PS C:\Work> $Error
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item <<<< -type directory -path $paths
Get-ChildItem : パス 'C:\Work\HOGE' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir <<<< HOGE
少し見づらいですが、2つのエラーが格納されていることが分かります。
$Error
変数は配列なので、下記のように要素番号を指定して1つずつエラーを取り出すことができます。
PS C:\Work> $Error[0]
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item <<<< -type directory -path $paths
また$Error
変数は、新しいエラーが発生すると常に$error[0]
へ書き込みます。以前に$error[0]
に代入されていたエラーは$error[1]
へ、$error[1]
のエラーは$error[2]
へと移動します。
このことから、最新のエラーは$error[0]
を参照すればよいことが分かります。
$?変数
この変数は、最後に実行したコマンドの実行状態を保持するブール変数です。直前の処理が成功した場合にはTrue
、それ以外の場合はFalse
となります。
まずは、この変数の動きを見てみましょう。何もエラーが発生していない状態で、$?
変数の中身を確認すると
PS C:\Work> $?
True
上記のようにTrue
を返します。
下記のようにエラー発生させ
PS C:\Work> Get-ChildItem HOGE
Get-ChildItem : パス 'C:\Work\HOGE' が存在しないため検出できません。
発生場所 行:1 文字:14
+ Get-ChildItem <<<< HOGE
$?
の値を確認すると
PS C:\Work> $?
False
上記のようにFalse
を返します。
この$?
変数は特にスクリプトの中で効果を発揮します。
下記はカレントディレクトリに「HOGE」が存在するかを確認していますが、存在しない場合にはエラーが発生します。しかし、2>&1
演算子を利用してエラー内容を$err
変数に書き込むので、エラーメッセージは表示されません。また、エラーが発生しても処理は続行します。
このような場合に$?
を使用することで、直前のコマンドが成功したか否かを確認することが可能となります。
$err = Get-ChildItem HOGE 2>&1 if ($?) {"エラーは発生しませんでした" }
else {"エラーが発生しました"}
-ErrorActionパラメータと$ErrorActionPreference変数
PowerShellでは、エラーの表示方法を制御することが可能で
- コマンドレット使用時に発生したエラー
- すべてのエラー
それぞれに対して行うことができます。
コマンドレット使用時のエラー表示を制御するには-ErrorAction
パラメータを、すべてのエラー表示の制御を行うには$ErrorActionPreference
変数を設定します。
設定可能な値は共通です。それぞれについて見ていきます。
continue
デフォルトではcontinue
になっています。エラーが発生した場合はメッセージが出力されます。
エラーの内容は$Error
変数に追加され、$?
変数はFalse
となります。スクリプトは次の行から実行されます。
silentlycontinue
エラーが発生してもメッセージは出力されません。
エラーの内容は$Error
変数に追加され、$?
変数はFalse
となります。スクリプトは次の行から実行されます。
stop
エラーが発生した時点で処理を中止します。
エラーの内容は$Error
変数に追加され、$?
変数はFalse
となります。スクリプトは停止します。
-ErrorActionパラメータの使用方法
このパラメータは、コマンドレット使用時に発生したエラーの表示を制御します。
-ErrorAction
パラメータにcontinue
を設定した場合は、エラーメッセージが出力されます。
PS C:\Work> Get-ChildItem Hoge -ErrorAction "continue"
Get-ChildItem : パス 'C:\Work\Hoge' が存在しないため検出できません。
発生場所 行:1 文字:14
+ Get-ChildItem <<<< Hoge -ErrorAction "continue"
-ErrorAction
パラメータにsilentlycontinue
を設定した場合は、エラーメッセージが出力されません。
PS C:\Work> Get-ChildItem Hoge -ErrorAction "silentlycontinue"
PS C:\Work>
-ErrorAction
パラメータにstop
を設定した場合は、エラーアクション設定によって実行が中止されたことを示すメッセージが表示され、処理を中止します。
PS C:\Work> Get-ChildItem Hoge -ErrorAction "stop"
Get-ChildItem : シェル変数 "ErrorActionPreference" が Stop に設定さ
れているため、コマンドの実行が停止しました。
パス 'C:\Work\Hoge' が存在しないため検出できません。
発生場所 行:1 文字:14
+ Get-ChildItem <<<< Hoge -ErrorAction "stop"
$ErrorActionPreference変数の使用方法
この変数に設定した値は、発生したエラーすべてのエラー表示を制御します。
$ErrorActionPreference
変数への値の設定は、=
演算子の左辺に$ErrorActionPreference
変数を、右側に設定する値を記述します。
試しに$ErrorActionPreference
変数へsilentlycontinue
を設定してみます。
PS C:\Work> $ErrorActionPreference = "silentlycontinue"
この状態で、エラーが発生するコマンドを実行してみます。
PS C:\Work> Get-ChildItem Hoge
PS C:\Work>
エラーメッセージは表示されません。
$ErrorActionPreference
変数にsilentlycontinue
を設定した効果が現れていることが分かります。(元に戻すには$ErrorActionPreference="Continue"
と入力してください。)
例外処理をする
PowerShellではtrap
文を用いることで、例外処理を行うことができます。trap
文の構文は下記の通りです。
trap [<例外の種類>]
{
trap文本体
}
「例外の種類」は省略することが可能です。
例えば下記では、1/$Null
を実行されるゼロ除算例外が発生するため、trap
へ制御が移り「例外発生」の文字列を表示します。
PS C:\Work> trap
>> {"例外発生" }
>> 1/$Null
>>
例外発生
0 で除算しようとしました。
発生場所 行:3 文字:3
+ 1/$ <<<< Null
breakで処理を中断する
次に、例外が発生したら処理を中断する方法について見てみましょう。中断するにはbreak
を使用します。
trap
{
"例外が発生しました"
break
} 1/$Null Write-Host "スクリプト終了"
このスクリプトは、例外が発生するとtrap
を実行するので「例外が発生しました」のメッセージを表示します。さらにbreak
が実行されエラーメッセージを表示し、処理を中断します。
この結果、「スクリプト終了」の文字列は表示されません。
PS C:\Work> ./trap2.ps1
例外が発生しました
0 で除算しようとしました。
発生場所 C:\Work\trap.ps1:7 文字:3
+ 1/$ <<<< Null
continueを使用する
次にtrap
の中でcontinue
を使用するとどうなるか、見てみましょう。
trap
{
"例外が発生しました"
continue
} 1/$Null Write-Host "スクリプト終了"
実行結果は下記のとおりで、例外が発生すると「例外が発生しました」のメッセージが表示され、最後の「スクリプト終了」が表示されます。
PS C:\Work> ./trap3.ps1
例外が発生しました
スクリプト終了
このようにcontinue
を使用した場合はエラーメッセージは表示されず、trap
を実行後、例外が発生した次の行から処理が再開されます。
まとめ
今回は
- エラーのリダイレクト
-ErrorRecord
オブジェクト- $Error変数
- $?変数
-ErrorAction
パラメータと$ErrorActionPreference
変数--ErrorVariable
パラメータ- 例外処理
について取り上げました。
PowerShellでは、エラーに対するさまざまな対処方法および内容の取得方法が準備されています。このことを理解し、スクリプト開発に役立てていただければと思います。
Windows PowerShell 入門(9)-エラー編的更多相关文章
- Windows PowerShell 入門(7)-関数編2
この連載では.Microsoftが提供している新しいシェル.Windows Power Shellの使い方を解説します.前回に引き続きPowerShellにおける関数の取り扱いとして.変数と関数のスコ ...
- Windows PowerShell 入門(3)-スクリプト編
これまでの記事 Windows PowerShell 入門(1)-基本操作編 Windows PowerShell 入門(2)-基本操作編 2 対象読者 Windows PowerShellでコマンド ...
- Windows PowerShell 入門(2)-基本操作編 2
前回に引き続きMicrosoftが提供している新しいシェル.Windows Power Shellの基本操作方法を学びます.基本操作編第2弾の今回は.パイプの使用方法を中心としたコマンドレットの操作方 ...
- Windows PowerShell 入門(10)-デバッグ編
対象読者 Windows PowerShellでコマンドレット操作ができる方 何らかのプログラミング経験があればなお良い 必要環境 Windows PowerShell デバッグメッセージの出力 Po ...
- Windows PowerShell 入門(8)-関数編3
この連載では.Microsoftが提供している新しいシェル.Windows PowerShellの使い方を解説します.今回は.フィルタ.スクリプトブロック.変数のスコープについて取り上げます. はじめ ...
- Windows PowerShell 入門(6)-関数編1
この連載では.Microsoftが提供している新しいシェル.Windows Power Shellの使い方を解説します.今回は.関数の作成基礎と引数.戻り値.Switchパラメータについて説明します. ...
- Windows PowerShell 入門(1)-基本操作編
Microsoftが提供している新しいシェル.Windows Power Shellの基本操作方法を学びます.インストール.起動終了方法.コマンドレット.命名規則.エイリアス.操作方法の調べ方について ...
- Windows PowerShell 入門(4)-変数と演算子
Windows PowerShellにおける変数と演算子の使用方法について学びます.今回は代表的な演算子として.算術演算子.代入演算子.論理演算子.比較演算子.範囲演算子.置換演算子.ビット演算子.型 ...
- Windows PowerShell 入門(5)-制御構文
Windows PowerShellにおける制御構文について学びます.数ある制御構文の中でもSwitch文は.他の言語に比べ豊富な機能が用意されています. 対象読者 Windows PowerShel ...
随机推荐
- flask get和post请求使用
直接看代码 #-*-coding:utf-8-*- from flask import Flask,url_for,redirect,render_template,request app = Fla ...
- 网络编程基础【day09】:socket解决粘包问题之MD5(八)
本节内容 1.概述 2.代码实现 一.概述 上一篇博客讲到的用MD5来校验还是用的之前解决粘包的方法,就是客户端发送一个请求,等待服务端的确认的这样的一个笨方法.下面我们用另外一种方法:就是客户端已经 ...
- JAVA-序列化深拷贝对象
序列化拷贝方法 @SuppressWarnings("unchecked") public static <T extends Serializable> T clon ...
- HDU 1020(连续同字符统计 **)
题意是要统计在一段字符串中连续相同的字符,不用再排序,相等但不连续的字符要分开输出,不用合在一起,之前用了桶排序的方法一直 wa,想复杂了. 代码如下: #include <bits/stdc+ ...
- PHP7 学习笔记(十五)Repository 模式实现业务逻辑和数据访问的分离
参考: 1.http://laravelacademy.org/post/3063.html
- springBoot的事物管理
springBoot的事物管理 1:springBoot 整合单数据源事物: Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务 ...
- django生产环境启动问题
unavailable modifier requested: 0 环境: nginx+uwsgi+django *** Starting uWSGI 2.0.16 (64bit) on [Wed J ...
- Ext.net NumberField要设置MinValue,MaxValue
<Items> <ext:NumberField ID="NumberField1" runat="server" FieldLabel=&q ...
- 使用 Topshelf 结合 Quartz.NET 创建 Windows 服务
Ø 前言 之前一篇文章已经介绍了,如何使用 Topshelf 创建 Windows 服务.当时提到还缺少一个任务调度框架,就是 Quartz.NET.而本文就展开对 Quartz.NET 的研究,以 ...
- Redis基础知识 之——发布/订阅
一.说明: 订阅,取消订阅和发布实现了发布/订阅消息范式(引自wikipedia),发送者(发布者)不是计划发送消息给特定的接收者(订阅者).而是发布的消息分到不同的频道,不需要知道什么样的订阅者订阅 ...