web-dev-qa-db-ja.com

PowerShellからWindowsコマンドプロンプトにエラーコード(ErrorLevel)を取得するにはどうすればよいですか?

WindowsコマンドプロンプトからPowerShellコマンドを起動して、テキストをファイルに置き換えようとしています。問題は、PowerShellコマンドが機能していない場合でも、常にErrorLevel = 0になることです。私の質問は、cmdを介してPowerShellを起動したときにエラーコードをErrorLevelに取り込む方法です。スクリプトをパーツとして作成するのではなく、Windowsコマンドプロンプトを使用してこれを作成したいことに注意してください。

これが私が言っていることの例です。印刷画面のエラーは、存在しないファイルを選択することによって意図的に作成され、エラーが発生した場合でもErrorLevelが0に等しいことを示します。

私が使用しているコマンドは次のとおりです($LastExitCode$ExitCodeを試しました):

powershell -NonInteractive -NoProfile -Command "(Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref; exit $LastExitCode"

しかし、私も同じことを試しました:

powershell -NonInteractive -NoProfile -Command "(Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref; exit $ExitCode"

Majkinetorのコメントに基づいて、私は次のことを試しましたが、うまくいきませんでした:(、PowerShellでエラーが発生した場合でも、DosでErrorLevel0を取得し続けます。

powershell -noprofile -command " try { (Get-Content HvsvmAppserver.ref) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref } catch {exit $LastExitCode}"

ファイル名に関連するエラーが存在しないことがはっきりとわかりますが、エラーレベルは常に0です。

私が欲しいのは、PowerShellコマンドの実行中に発生するエラーごとに0以外のエラーコードを取得することです。

私が読んだいくつかのコメントに基づいて、私は言いたいです:私はPowerShellとDosコマンドを介してそれを作りたいのですが、別の方法ではありません。私は自分のエラーコードやパーソナライズされたエラー管理を作りたくありません!私が欲しいのは、PowerShell(コード、スクリプトなど)でエラーが発生したときに、Dosのエラーレベルがこのエラーコードを取得することです(独自のコードを作成したくありません)。答えのある方は大歓迎ですが、ここにいる方は、欲しいものを変えたり、写真を削除したりして、役に立たないコメントでコメントするだけです...提供する以外はコメントしないでくださいヘルプと私の質問への回答は、他の何かを提案することではなく、特定の何かについてのヘルプを求めています。件名を他のものに変更しないでください。このサイトのアイデアは、役に立たないものを追加するのではなく、ヘルプを提供することです。役に立たないコメント。

Error 2

8
JustGreat

Cmd.exeシェルでこのコードを試してください:

C:> powershell -noprofile -command " try { 1/0 } catch {exit 22}"

C:> echo %errorlevel%
22

したがって、tryブロックにコマンドを追加します。 PowerShell以外のコマンドを呼び出すことが発生した場合は、exit $LastExitCodeできます(ただし、tryブロック内から)。


[〜#〜]編集[〜#〜]

OK、動作していないコードで何が起こっているのかはわかっています。Get-Contentが 非終了エラー を生成するため、キャッチブロックを通過することはありません。あなたはそれについて注意しなければなりません:

C:> Powershell -Command "try { (Get-Content HvsvmAppserver.ref -ea stop) -replace '-Dfr.base0.role=', '-Dfr.base0.role=USR_ROLE'| Set-Content -encoding ASCII HvsJvmAppserver.ref -ea stop } catch {$_; exit 123 }"

Get-Content : Cannot find path 'C:\Users\majkinetor\HvsvmAppserver.ref' because it does not exist.
At line:1 char:8
+ try { (Get-Content HvsvmAppserver.ref -ea stop) -replace '-Dfr.base0. ...
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\majkinetor\HvsvmAppserver.ref:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

C:> echo %errorlevel%
123

両方のコマンドに追加した-ea stopに注意してください(ErrorActionより短い)。私のソリューションは最初は正しかったのですが、スクリプトも正しく設計する必要があることを理解する必要があります。 catchの代わりにtrapを使用することもできますが、それでもEAstopを使用する必要があります。おそらく、スクリプトにあまり依存しない最短の一般的な解決策は次のとおりです。

   $ErrorActionPreferance = 'Stop'
   <your script goes here, no need for -ea stop in it>
   trap { exit 123 }

問題のスクリプトが$ErrorActionPreferenceを変更した場合(これはめったに発生しません)は機能しませんが、それ以外の場合はすべて機能します。

5
majkinetor

@majkinetorによる提案は間違いなく機能します。私はこれを意味します:

powershell -Command "try {(gc "C:\test.txt" -ea stop) -creplace 'test', 'work' | Out-File -encoding ASCII "C:\test.txt" -ea stop} catch{ exit 1}"

ファイルパスが正しい場合、文字列が置き換えられます。ファイルパスが正しくない場合-上記のスニペットでcmdセッションのエラーレベルが1に設定されます。

私が遭遇した問題は、これをJenkinsビルドに失敗させたい場合です。私はビルドステップWindowsバッチコマンドを実行します。トリックは、エラー時にビルドを失敗させたい場合は、上記のコマンドのみが必要なことです。後で別のものがあり、それが成功した場合、ビルドは成功します。

0
joro

だから私のコメントに基づいてこれを答えとして置くために:

それがあなたが渡している値であるため、あなたはゼロを得ています。変数のいずれかを終了コードとして使用する場合は、それらを何かに設定する必要があります。

あなたが答えたもの:

@ShawnMeltonありがとうございますが、うまくいきませんでした。独自のエラーコードやパーソナライズされたエラー管理を作成したくありません。私が欲しいのは、PowerShell(コード、スクリプトなど)でエラーが発生したときに、Dosのエラーレベルがこのエラーコードを取得することです(独自のコードを作成したくありません)。コードで何を意味するのか説明できますか?私はあなたのコメントを理解していないかもしれませんか?それがあなたの側から素晴らしいことを助けようとしてくれてありがとう。

powershell.exeを呼び出しているので、終了コードをコマンドプロンプトに返します。常にゼロ(0)として返されます。正しくないPowerShellコードを実行しても、常にゼロになります。 powershell.exe自体は、渡されたコマンドを正常に実行しているため、実行可能ファイル自体に何らかの理由でエラーが発生しない限り、常にゼロになります。 PowerShell.exeがゼロ以外のものを返すようにする場合は、PowerShellコマンドでexit xxを使用する必要があります。ここで、xxは整数です。 enter image description here

ここで実行するかどうかに関係なく、コマンドプロンプトからPowerShellを呼び出さないという点は依然として有効です。 exit 99のようなものを使用しても、実行可能ファイルが常に上書きされてゼロが返されるという保証はありません...それはまさにその動作方法です。 Windows 10を搭載したラップトップで試してみると、さまざまな結果が得られました。SSISパッケージからPowerShellスクリプトを呼び出さなければならなかったときに、本番環境で以前にテクニックを使用したことがあり、それが目的を果たしました。ただし、その状況では、バッチファイルから呼び出していなかったため、期待どおりに機能しました。

0
user847990

最後に外部コマンドを使用すると、エラーレベルが設定されます。パイプを「^」で引用しています。

powershell echo hi ^| findstr hi2

または、$をテストできますか?ゼロ以外の数値で終了します。

powershell 1/0; if (! $?) { exit 1 } 

実際、LASTコマンドレットで終了の有無にかかわらずエラーが発生した場合は、cmdのエラーレベルを設定する必要があります。

このようなことをして、エラーの数で終了することができます。

powershell $errorcount = $error.count; 1/0; echo hi; exit $error.count - $errorcount

スクリプト終了エラーは、エラーレベルを設定します。

powershell throw 'hi'

元の問題についてもっと考えます。括弧を使用しない場合、現在のパイプラインには例外があるため、ファイルが見つからない場合はエラーレベルが設定されます。ただし、出力ファイルは異なっている必要があります。スクリプトとして実行しても同じ結果は得られません(UNIXでもありません)。

powershell "get-content foo2 | foreach { $_ -replace 'a','b' } | set-content foo3"

get-content : Cannot find path 'C:\Users\admin\foo2' because it does not exist.
At line:1 char:1
+ get-content foo2 | foreach { $_ -replace 'a','b' } | set-content foo3
+ ~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\admin\foo2:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand


echo %errorlevel%

1
0
js2010