2

The title pretty much sums it up, but I'll elaborate on my question. Out of curiosity I've been putting commands in a block (usually with one command that won't work) and seeing if I can suppress the error messages and output a custom one. I tried two methods, the first one failed but the second worked.

1

@echo off
(
    echo Blah
    ehco Blah & rem Intentional mistake
    echo Blah
) 2>nul||echo One of the commands failed.
pause>nul

Output:

Blah
Blah

2

@echo off
call :block 2>nul||echo One of the commands failed.
pause>nul
exit
:block
(
    echo Blah
    ehco Blah & rem Intentional mistake
    echo Blah
)
goto :eof

Output:

Blah
Blah
One of the commands failed.

So, I've got the the second part of my question answered, now I just need to know how to (if one of the commands failed) suppress any output except the custom error message. So, the desired output would be One of the commands failed.. How would I go about doing this?

NOTE: I've heard that you can do something like echo Blah 2>&1nul or something like that, and I guess that would be the way to go. But I'm also guessing that would make it suppress the output every time the command is run, not just when there's an error message.

Also, in your answer, if you could do a brief explanation of why the first script failed, that would be dandy.

4

2 に答える 2

1

非常に興味深いトピックですが、あなたは何も解決していません-あなたは自分自身をだましました:-)

私はあなたのコードのわずかなバリエーションを実行します、そしてあなたが期待しているように物事はもはや機能しません!

@echo off
:: clear any existing error
call;

echo %errorlevel%
(
    echo Blah
    ehco Blah & rem Intentional mistake
    echo Blah
) 2>nul||echo One of the commands failed.
echo %errorlevel%

echo(
echo --------------------------
echo(

echo %errorlevel%
call :block 2>nul||echo One of the commands failed.
echo %errorlevel%
exit /b

:block
echo Blah
echo Blah
echo Blah
exit /b

---出力---

0
Blah
Blah
9009

--------------------------

9009
Blah
Blah
Blah
One of the commands failed.
9009

通常、後のコマンド||は、前のコマンドが失敗した場合にのみ起動します。||オペレーターは通常、%ERRORLEVEL%変数を直接読み取ることはなく、通常、前のコマンドのエラーステータスを直接検出します。

最初のコードセットでは、コマンドの1つが失敗し、ERRORLEVELが9009に設定されました。ただし、ブロック内の最後のコマンドが成功したため、条件付き失敗メッセージは発生しません。

コードの2番目のブロックはCALLを使用します。CALLを実行すると、通常、復帰時の現在の%ERRORLEVEL%がCALLコマンドの復帰状態として使用されます。ルーチン入力時のERRORLEVELは9009であり、ルーチン内のどのコマンドもエラーをクリアしないため、CALLステートメントのエラーステータスとして9009が返されます。EXIT / Bの後に追加パラメーターとしてエラーレベルを指定することにより、戻りコードを任意の値に強制できます。たとえば、exit /b 0

どのコマンドが常にERRORLEVELを設定し、どのコマンドがエラーが発生した場合にのみERRORLEVELを設定するかを理解しようとすると、少し注意が必要になる場合があります。内部コマンドはエラーが発生した場合にのみERRORLEVELを設定し、コマンドが成功した場合は以前のERRORLEVELをクリアしないと思います。(私は.BAT拡張を想定しています。.CMD拡張によって動作が変わると思います)

ほとんどの(すべて?)外部コマンドは常にERRORLEVELを設定します。実行可能ファイル次第ですが、ほとんどの外部コマンドは、成功した場合は0を返し、失敗した場合はゼロ以外を返します。

コードのブロックには内部コマンドと外部コマンドが混在している可能性があるため、いずれかのコマンドが失敗した場合に最終的なERRORLEVELがゼロ以外になると想定することはできません。介在する外部コマンドがERRORLEVELをクリアした可能性があります。各コマンドの戻りコードを確認し、ブロック内のエラーの存在を保持するようにエラー変数を設定する必要があります。その後、EXIT/Bを使用して必要なエラーコードを明示的に返すことができます。

すべてのコマンドが成功したときにのみstdoutを出力すると考える唯一の方法は、すべてのstdoutを一時ファイルにリダイレクトし、コマンドが失敗したかどうかを確認することです。ブロックの最後で、エラーがなかった場合にのみ、一時ファイルの内容を入力できます。次に、関係なく一時ファイルを削除します。

于 2013-03-07T04:18:21.880 に答える
0

ここに私のテストバッチがあります:

@echo OFF
call :block 2>nul||echo One of the commands failed 1.
call :block2 2>nul||echo One of the commands failed 2.
GOTO :eof

:block
(
    echo Blah
    ehco Blah & rem Intentional mistake
    echo Blah
)
goto :eof
:block2
(
    echo Blah
    echo Blah & rem Intentional mistake
    echo Blah
)
goto :eof

これを実行すると、

Blah Blah コマンドの 1 つが失敗しました 1. Blah Blah Blah コマンドの 1 つが失敗しました 2.

.bat または .cmd として保存されたかどうかに関係なく

私は古いエラーレベル理論に賛成です - BLOCK2 サブルーチンを呼び出す前にエラーレベルを強制的に 0 にすると、問題が解決しました。

したがって、得られる動作は既存の errorlevel 設定に依存し、予期しない結果が生じる可能性があります...

于 2013-03-07T05:09:48.593 に答える