4

$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/catchwithのこの基本的なアプローチを使用する多くの例をオンラインで見た$ErrorActionPreference = "Stop"ので、これを機能させることができるはずです。

したがって、私の質問は基本的に次のとおりです。このスクリプトを自分が思うように機能させることはできますか? そうでない場合、私は何を誤解していますか?この種のエラーをキャッチするにはどうすればよいですか? もしそれが助けになるなら、私はこれに非常に詳細な例外処理は必要ありません.タスクモニターが私に警告できるように、何か問題が発生したときに知る必要があるだけです. powershell.exe からのゼロ以外のリターン コードで十分です。

と の使用を検討していますが$?、と同じ問題が発生し、どちらも実行された最後のステートメントにのみ適用されるに違いありません。これは、実際のスクリプトがこの例よりもかなり長いため、理想的とは言えません。$LASTEXITCODE$?$error

編集:
OK、以来、Windows 実行可能ファイル (sqlcmd など) は、$errorゼロ以外の終了コードを返したとしても、コレクションに何も追加しないことを知りました。$error私が正しく理解している場合、コマンドレットでのみ使用されます。Windows 実行可能終了コードを認識し、ゼロ以外の値に対して false に設定されるため、同様に$LASTEXITCODE使用することもできましたが、スクリプトを繰り返し使用して動作させることができました。$?

要約すると、コマンド ラインから実行したときのスクリプトの動作は、正しく、予期された動作です。ただし、PowerShell ISE とは異なる結果が得られた理由はまだわかりません。

4

1 に答える 1

0

私にとっては、使用してバッチコマンドを呼び出しcmd /C <command>ていますが、同様の問題があります。ゼロ以外のリターン コード$?は正しく設定されていますが、オブジェクトがなく$error(powershell はどのように認識するのでしょうか? これで問題ありません)、コードは ISE でもコマンド ライン実行でも同様に動作します。

私の問題は、そのような場合に$ErrorActionPreference = "Stop"例外がスローされないことです。$errorおそらく、投げるオブジェクトがないためです。だから今$?、きちんとしていない他のスクリプトやプログラムを呼び出すたびにチェックする必要があります。そのような状況に対する適切な解決策を考え出す必要があります (おそらく、外部スクリプト/プログラムへの呼び出しが失敗したという組み込みの例外をスローすることによって)

于 2012-08-01T18:13:50.873 に答える