対象読者

  • 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

 では、エラーの内容が変数に代入されているかを確認してみましょう。

caption
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
-ErrorVariableパラメータ
 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を使用します。

trap2.ps1
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を使用するとどうなるか、見てみましょう。

trap3.ps1
trap
{
"例外が発生しました"
continue
} 1/$Null Write-Host "スクリプト終了"

 実行結果は下記のとおりで、例外が発生すると「例外が発生しました」のメッセージが表示され、最後の「スクリプト終了」が表示されます。

PS C:\Work> ./trap3.ps1
例外が発生しました
スクリプト終了

 このようにcontinueを使用した場合はエラーメッセージは表示されず、trapを実行後、例外が発生した次の行から処理が再開されます。

まとめ

 今回は

  • エラーのリダイレクト
  • -ErrorRecordオブジェクト
  • $Error変数
  • $?変数
  • -ErrorActionパラメータと$ErrorActionPreference変数
  • --ErrorVariableパラメータ
  • 例外処理

 について取り上げました。

 PowerShellでは、エラーに対するさまざまな対処方法および内容の取得方法が準備されています。このことを理解し、スクリプト開発に役立てていただければと思います。

Windows PowerShell 入門(9)-エラー編的更多相关文章

  1. Windows PowerShell 入門(7)-関数編2

    この連載では.Microsoftが提供している新しいシェル.Windows Power Shellの使い方を解説します.前回に引き続きPowerShellにおける関数の取り扱いとして.変数と関数のスコ ...

  2. Windows PowerShell 入門(3)-スクリプト編

    これまでの記事 Windows PowerShell 入門(1)-基本操作編 Windows PowerShell 入門(2)-基本操作編 2 対象読者 Windows PowerShellでコマンド ...

  3. Windows PowerShell 入門(2)-基本操作編 2

    前回に引き続きMicrosoftが提供している新しいシェル.Windows Power Shellの基本操作方法を学びます.基本操作編第2弾の今回は.パイプの使用方法を中心としたコマンドレットの操作方 ...

  4. Windows PowerShell 入門(10)-デバッグ編

    対象読者 Windows PowerShellでコマンドレット操作ができる方 何らかのプログラミング経験があればなお良い 必要環境 Windows PowerShell デバッグメッセージの出力 Po ...

  5. Windows PowerShell 入門(8)-関数編3

    この連載では.Microsoftが提供している新しいシェル.Windows PowerShellの使い方を解説します.今回は.フィルタ.スクリプトブロック.変数のスコープについて取り上げます. はじめ ...

  6. Windows PowerShell 入門(6)-関数編1

    この連載では.Microsoftが提供している新しいシェル.Windows Power Shellの使い方を解説します.今回は.関数の作成基礎と引数.戻り値.Switchパラメータについて説明します. ...

  7. Windows PowerShell 入門(1)-基本操作編

    Microsoftが提供している新しいシェル.Windows Power Shellの基本操作方法を学びます.インストール.起動終了方法.コマンドレット.命名規則.エイリアス.操作方法の調べ方について ...

  8. Windows PowerShell 入門(4)-変数と演算子

    Windows PowerShellにおける変数と演算子の使用方法について学びます.今回は代表的な演算子として.算術演算子.代入演算子.論理演算子.比較演算子.範囲演算子.置換演算子.ビット演算子.型 ...

  9. Windows PowerShell 入門(5)-制御構文

    Windows PowerShellにおける制御構文について学びます.数ある制御構文の中でもSwitch文は.他の言語に比べ豊富な機能が用意されています. 対象読者 Windows PowerShel ...

随机推荐

  1. pickle详解

    一.简介 在机器学习中,我们常常需要把训练好的模型存储起来,这样在进行决策时直接将模型读出,而不需要重新训练模型,这样就大大节约了时间 Python提供的pickle模块就很好地解决了这个问题,它可以 ...

  2. python 第一类对象 闭包 迭代器

    ########################总结########################### 1. 函数名 -> 第一类对象 函数名就是变量名. 函数可以赋值 函数可以作为集合类的 ...

  3. 【1】【leetcode-130】 被围绕的区域

    (DFS思路对,写复杂了) 给定一个二维的矩阵,包含 'X' 和 'O'(字母 O). 找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充. 示例: X X X X X O ...

  4. 关于Ant脚本

    在开发中,一个项目要经历单元测试l,集成测试,系统测试,测试过程中可能要不断修改代码,Ant脚本,通过一个xml文件,封装一系列繁琐又常用的操作,通过Ant指令执行xml脚本来批处理创建删除任务,编译 ...

  5. GIL 全局解释器

    全局解释器锁 GIL 相当于给python解释器加了一把互斥锁 每一个进程都有一把互斥锁,所有线程必须先拿到解释器,才能执行代码, 同一进程下,所有线程并发 在 Cpython 解释器下,多个进程可以 ...

  6. 跨域请求传递Cookie问题

    问题描述 前后端完全分离的项目,前端使用Vue + axios,后端使用SpringMVC,容器为Tomcat. 使用CORS协议解决跨域访问数据限制的问题,但是发现客户端的Ajax请求不会自动带上服 ...

  7. mysql中间件

    一.分类为:负载均衡类和数据切分类 1.负载均衡中间件提供了请求的转发,降低了单节点的负载,如haproxy,mysql-proxy,mysql-router 2.数据切分中间件按照不同的路由算法分发 ...

  8. 字符设备驱动(一)---led

    一.总体架构 二.硬件电路 1.硬件原理图 2.寄存器配置 三.代码编写 写linux的设备驱动操作的是系统的虚拟地址,并不是像裸机程序一样操作的是物理地址. 物理地址要映射成虚拟地址,就要用到ior ...

  9. [译]Debug ASP.NET Core 2.0源代码

    原文 首先你的VS必须为VS 2017 15.3或以上版本. 打开你的Startup类,在ConfigureServices方法上设置个断点,按F5 Debug应用. 在Call Stack(调用堆栈 ...

  10. solr window环境安装配置和管理页面基本使用

    solr介绍 来自官网http://lucene.apache.org/solr/解释: Solr is highly reliable, scalable and fault tolerant, p ...