$error
エラーの検出と対応に使用する PowerShell スクリプトを作成しています。私の問題は$error
、スクリプトの実行方法に応じて、オブジェクトの動作が異なることです。対話的に (具体的には PowerShell ISE から) 実行すると、エラーがコレクションに追加されますが、コマンド ラインから同じスクリプトを実行すると、同じエラーが発生しますが、コレクションには追加されません。
スクリプトは次のとおりです (問題を説明するために簡略化しています)。
# export_exception_test.ps1
# show me how many errors before we start
"Count = " + $error.Count
try {
# treat non-terminating errors as terminating errors.
$ErrorActionPreference = "Stop"
# echo the setting to output
$ErrorActionPreference
# use sqlcmd to save the output of stored procedures to text files.
# The first and third call will fail because the output folder does not exist.
# The second call will succeed.
'first call to sqlcmd'
sqlcmd -S myserver\myinstance -E -s `"`t`" -Q "EXEC mydatabase.dbo.FI_Codes" -b -o "B:\Exports_new\FI_Codes.txt"
'second call to sqlcmd'
sqlcmd -S myserver\myinstance -E -s `"`t`" -Q "EXEC mydatabase.dbo.FI_Codes" -b -o "B:\Exports_newt\FI_Codes.txt"
'third call to sqlcmd'
sqlcmd -S myserver\myinstance -E -s `"`t`" -Q "EXEC mydatabase.dbo.FI_Codes" -b -o "B:\Exports_new\FI_Codes.txt"
# and a whole bunch more of these...
# The error count should be two more than when we started.
"Count = " + $error.Count
# And this should be the most recent error message
"Message = " + $error[0].Message
}
catch [Exception]
{
'exception was caught!!!'
"Count in catch clause = " + $error.Count
$_.Exception.Message
# the ultimate goal is to return a non-successful return code when the exports fail
exit 1
}
finally {
# set this back to what it was
$ErrorActionPreference = "Continue"
# primitive trace output
'finally.'
}
これを PowerShell ISE から実行すると、期待どおりに動作します。SQLCMD は終了しないエラーを発生させ、これをキャッチして処理します。出力は次のとおりです。
PS U:\> C:\Users\etmatt\Documents\PowerShellScripts\export_exception_test.ps1
Count = 0
Stop
first call to sqlcmd
exception was caught!!!
Count in catch clause = 1
Sqlcmd: Error: Error occurred while opening or operating on file B:\Exports_new\FI_Codes.txt (Reason: The system cannot find the path specified).
finally.
しかし、スケジュールされたタスクをセットアップする場合と同様に、コマンド ラインから実行すると、何も追加され$error
ず、例外も発生しません。出力は次のとおりです。
C:\Users\etmatt>powershell.exe -file "C:\Users\etmatt\Documents\PowerShellScripts\export_exception_test.ps1"
Count = 0
Stop
first call to sqlcmd
Sqlcmd: Error: Error occurred while opening or operating on file B:\Exports_new\FI_Codes.txt (Reason: The system cannot find the path specified).
second call to sqlcmd
third call to sqlcmd
Sqlcmd: Error: Error occurred while opening or operating on file B:\Exports_new\FI_Codes.txt (Reason: The system cannot find the path specified).
Count = 0
Message =
finally.
C:\Users\etmatt>
cmd.exe ではなく、powershell コマンド ラインからスクリプト ファイルを実行しても、同じ結果が得られます (これは理にかなっています)。例えば:
PS C:\> ."C:\Users\etmatt\Documents\PowerShellScripts\export_exception_test.ps1"
これは、実行コンテキスト、またはパーサー モードに関する何かと関係があると思われますが、これはまだ十分に理解していないか、またはプロファイルでさえある可能性があります (ただし、これまでのところ、同じ PC から同じアカウントですべてを実行してきました)。 . try/catch
withのこの基本的なアプローチを使用する多くの例をオンラインで見た$ErrorActionPreference = "Stop"
ので、これを機能させることができるはずです。
したがって、私の質問は基本的に次のとおりです。このスクリプトを自分が思うように機能させることはできますか? そうでない場合、私は何を誤解していますか?この種のエラーをキャッチするにはどうすればよいですか? もしそれが助けになるなら、私はこれに非常に詳細な例外処理は必要ありません.タスクモニターが私に警告できるように、何か問題が発生したときに知る必要があるだけです. powershell.exe からのゼロ以外のリターン コードで十分です。
と の使用を検討していますが$?
、と同じ問題が発生し、どちらも実行された最後のステートメントにのみ適用されるに違いありません。これは、実際のスクリプトがこの例よりもかなり長いため、理想的とは言えません。$LASTEXITCODE
$?
$error
編集:
OK、以来、Windows 実行可能ファイル (sqlcmd など) は、$error
ゼロ以外の終了コードを返したとしても、コレクションに何も追加しないことを知りました。$error
私が正しく理解している場合、コマンドレットでのみ使用されます。Windows 実行可能終了コードを認識し、ゼロ以外の値に対して false に設定されるため、同様に$LASTEXITCODE
使用することもできましたが、スクリプトを繰り返し使用して動作させることができました。$?
要約すると、コマンド ラインから実行したときのスクリプトの動作は、正しく、予期された動作です。ただし、PowerShell ISE とは異なる結果が得られた理由はまだわかりません。