• 締切済み

終了コード errorlevel の考え方について

こんばんは。 OSはWindowsXP Proを使っています。 テキストファイルに書いてある値を 終了コードにするバッチファイルを作成しました。 以下の2ファイルを同じディレクトリに保存します。 test.txt ┌--------┐   1 └--------┘ test.bat ┌---------------------------------------┐   @echo off   find "0" test.txt   if not errorlevel 1 exit /b 0   find "1" test.txt   if not errorlevel 1 exit /b 1   echo テキストは0~1の値ではありません。   exit /b 2 └---------------------------------------┘ この状態で次のように実行します (1) C:\>test.bat ---------- TEST.TXT ---------- TEST.TXT 1 (2) C:\>echo %errorlevel% 1 (3) C:\>set errorlevel=0 (4) C:\>echo %errorlevel% 0 ※ここでtest.txtの中の数字を2にします。 (5) C:\>test.bat ---------- TEST.TXT ---------- TEST.TXT テキストは0~1の値ではありません。 (6) C:\>echo %errorlevel% 0 (7) C:\>set errorlevel= (8) C:\>echo %errorlevel% 2 となります。 (2)の結果から、(1)で実行した「exit /b 1」でerrorlevelに1が格納されることが判ります。 しかし、(6)の結果から、(3)で実行した「set errorlevel=0」が (5)で実行した「exit /b 2」より優先されていることが判ります。 しかし(7)でerrorlevelの値を消去したように思われますが、 (8)の結果から、(3)のセットを消去しつつ(5)で実行した「exit /b 2」を記憶しているように見えます。 この挙動について、どのように理解すれば良いのでしょうか。 また「exit /b ○」と「set errorlevel=○」でセットする違いについて教えて頂ければと思います。 お願いします。

みんなの回答

  • notnot
  • ベストアンサー率47% (4845/10255)
回答No.2

ERRORLEVELは、一般の環境変数と異なり、SET で値を代入してはいけません。(参考: set /? で表示される最終ページ) SET を使うと一般の環境変数となってしまい、次にSETするまで値は変わりません。コマンドの実行結果と切り離されると言うことです。 %ERRORLEVEL%は、環境変数ERRORLEVELがセットされていないときに限って、直前のコマンドの実行結果ステータスに置換されます。 (7)によってアンセットされたので、再びコマンド実行結果を表すようになりました(8)。 環境変数ERRORLEVELに値がセットされているかどうかは、SET ERRORLEVELでわかります。つまり、%ERRORLEVEL%をコマンドの実行結果として使うためには、 C:\>set errorlevel 環境変数 errorlevel が定義されていません という状態でないといけません。 %ERRORLEVEL%をゼロにしたければ、 C:\>cd とかの正常終了するコマンドを打てばいいです(ECHOは除く)。

Miyabi__
質問者

お礼

回答ありがとうございます。 「一般の環境変数」という考え方が判りませんが、変数と考えれば良いのでしょうか。 「set /?」で -------------------------------------------------------------- コマンド拡張機能が有効な場合、 SETによって表示される変数の一覧には現れない いくつかの動的な環境変数があります。 これらの変数の値は、変数の値が展開されるときに動的に計算されます。 ユーザーがこれらの名前の変数を明示的に定義する場合、 その定義は下記の動的な定義を無効にします。 -------------------------------------------------------------- とありました。 その文章以下に書いてある%CD%~%CMDCMDLINE%はSETで値を設定してはいけないということですね。 ・ERRORLEVELの値は実行結果により、動的に値が変更される。 ・SETで値を代入すると、動的に設定された値よりSETで代入した値を優先して参照する。 という理解です。 「set errorlevel=○」で設定した値を消去するには「set errorlevel=」 「exit /b ○」で設定した値を消去するには「C:\>cd」 を行えばよいのですね。 cd以外でも C:\>dir を実行した所、「exit /b ○」の終了コードが無効になったことを確認しました。

  • f272
  • ベストアンサー率46% (7995/17088)
回答No.1

set errorlevel=○ とすると環境変数errorlevelの値がセットされる。 exit /b ○ とするとシステム変数errorlevelの値がセットされる。これは自動的に環境変数errorlevelにもセットされる。 echo %errorlevel% としたとき環境変数errorlevelがセットされていればその値を書く。セットされていなければシステム変数errorlevelその値を書く。 set errorlevel= としたとき消去されるのは環境変数errorlevelの値である。

Miyabi__
質問者

補足

回答ありがとうございます。 「環境変数」と「システム変数」という違いがあるのですね。 どのような違いがあるのか、今の私にはまだ判らないのですが。 「コントロールパネル」→「システム」→「詳細設定」→「環境変数」→「システム環境変数」 に「変数名」「変数値」を設定した所、回答者様がおっしゃる所の環境変数の値になりました。 「echo %errorlevel%」で 環境変数がセットされていればその値を、セットされていなければシステム変数を表示する、 は理解しました。 一つだけ腑に落ちないのが (4)で環境変数に0がセットされましたが、 (6)で0を表示しているということは (5)ではシステム変数に2をセットしているが、環境変数には2をセットしていないことになります。 このことが >exit /b ○ >とするとシステム変数errorlevelの値がセットされる。これは自動的に環境変数errorlevelにもセットされる。 に矛盾していると考えました。お言葉を返すようですみません。

関連するQ&A

  • bat サブルーチンのERRORLEVELについて

    バッチのサブルーチンのERRORLEVELについて質問です。 サブルーチン内でERRORLEVELを返すコマンドを実行したいのですが、 親ルーチンにそのERRORLEVELを共有したくない場合、何か方法はありますか? ============================================================ [1.bat] SET MSG1="NOTFOUND" SET MSG2="found!" echo %ERRORLEVEL% FIND %MSG1% 2.bat REM %ERRORLEVEL%は1に echo %ERRORLEVEL% CALL :LOG echo %ERRORLEVEL% FIND %MSG2% 2.bat REM %ERRORLEVEL%は0に echo %ERRORLEVEL% CALL :LOG echo %ERRORLEVEL% REM %ERRORLEVEL%は0であって欲しいが0に pause EXIT 1 :LOG FIND %MSG1% hogehoge.log REM %ERRORLEVEL%は1に ============================================================ [2.bat] found! ============================================================ [hogehoge.log] 空 ============================================================

  • ERRORLEVELの使い方

    ERRORLEVELの使い方について質問させて頂きます。 echo Start cmd /c test1.bat if %ERRORLEVEL% neq 0 echo 1>mylog.txt else echo 2> mylog.txt exit rem test1.batの内容は、下記のようなもの rem xxx.exe 環境変数 %ERRORLEVEL%は、DOSプロンプトであれ、 チャイルドプロセス test1.bat であれ、とにかく エラーを保持するとのことですが、 上記のスクリプトが、どんな時でも、本当に正しく動くのか、心配です。 どうせ、ERRORLEVELをみて、何がしかの処理をするなら、 チャイルドプロセスの中で、 xxx.exeの次で、記述すべきではないかと考えます。 はたまた、別の世界(このDOSプロンプト、及びそのチャイルドプロセス以外)での エラーは、このERRORLEVELには、影響しないのでしょうか? さしあたり、自分で実験をしてみて、上記のバッチ、或いは、チャイルドプロセスにて記述 いずれも、動作は、期待通りでした。しかし、だからといって、どんな時でも、 期待通りに動くのかは、不明です。   ERRORLEVELは、エラーを発生させるルーチンの直下で評価すべきであり   そのルーチンがチャイルドプロセスであれば、チャイルドプロセスの中で処理すべき。   (cmd /cで戻って、ERRORLEVELを評価するのは、正しくない) ただ、これに拘ると、スクリプトが分散されてしまい、見通しが悪くなってしまいます。 宜しく、サジェスチョンをお願い申し上げます。

  • FOR文内でサブルーチンをCALLした際の、ERRORLEVELの取得

    ファイルをコピーしてからFOR文により6回処理を繰り返すような バッチファイルを作成しようと思っています。 そのFOR文内でコールしたサブルーチンのERRORLEVELがうまく取得できません。ファイルコピーをしなければ値が取得できるのですが。。。 何が 原因なのか皆目見当つかずで行き詰ってしまいました。 どなたか 教えてください。 宜しく御願いします。 @echo off copy test.txt test.txt.bak for /L %%A in (0,1,5) do ( call :test echo 戻り値:%ERRORLEVEL% ) :test exit /b 99

  • BATのIF文について質問

    @echo off cls set LOGFILE=C:\%COMPUTERNAME%.log find C:\temp\setting.txt "SERVER01" /I if %ERRORLEVEL% == 1 GOTO END if %ERRORLEVEL% == 0 ( set MESSAGE=SEVER01の環境です echo %MESSAGE% echo %MESSAGE% >> %LOGFILE% GOTO SET1 ) :SET1 echo テスト >> %LOGFILE% :END こんな簡単なBATを作成してみましたがERRORLEVELが0の時処理されません (「SEVER01の環境です」がLOGに書き込まれません) (もちろんsetting.txtには「SERVER01」の文字が入ってます) (FINDのあと、「echo %errorlevel」を記述して0にもなっているのですが) IFの構文として間違っていますか?どなたかご教授ください。 OSはWindowsXP SP3 64Bitです。

  • DOS終了コードの確認

    有識者の方、バッチファイルの終了コードの確認方法について、ご教授願います。当方、終了コード判定のBAT作成は初めてです。 質問: TXT(a.txt)ファイル、文字列検索を行った結果、該当の文字列が見つかった場合、終了コードを"0"では無く、"1"でバッチファイルを終了する場合(EXITコマンド終了コード1)、バッチファイルの終了コード"1"が正しく出されているのか確認の仕方を教えてください。 よろしくお願い致します。 +++temp.bat+++++ Find C:\temp\a.txt "aaa" →%ERRORLEBEL%の結果 0 IF NOT ERRORLEVEL 1 (exit /B 1)

  • バッチファイル 戻り値

    いつも大変御世話になっております。 WindowsVISTA環境で以下バッチ【ABC.bat】が稼動します。 "ABC.bat"------------------------------------------------- @ECHO ON set bat_name="ABC.bat" call DEF.bat echo %bat_name% は戻り値 %ERRORLEVEL% を受け取りました。 "ABC.bat"------------------------------------------------- 上記バッチの構文では以下バッチDEF.batを起動させ、ERRORLEVELを取得させます。 "DEF.bat"------------------------------------------------- @ECHO ON set bat_name="DEF.bat" exit /b 10 "DEF.bat"------------------------------------------------- 実行結果は予想していたものと違っていました。 予想していた実行結果 : "ABC.bat" は戻り値 10 を受け取りました。 実際の実行結果     : "DEF.bat" は戻り値 10 を受け取りました。】 %ERRORLEVEL%のみを取得したかったのですが DEF.bat の set bat_name="DEF.bat" までも取得してしまいました。 bat_name はどうしても "ABC.bat"とCALLする側の変数を使用したいのですが 制御は難しいでしょうか? echo %bat_name% は戻り値 %ERRORLEVEL% を受け取りました。 の直前に 再度 set bat_name="ABC.bat" と記述しなければダメでしょうか? 尚、都合上、ECHO文と変数名は変えたくありません。 もしご存知の方がいらっしゃるようでしたら、お手数ですが 実現可能かどうかをご回答願いますでしょうか? 以上、何卒宜しくお願い致します。

  • echo と%ERRORLEVEL%の値について

    今日の日付から7日前の日付をテキストファイルに保存しようとし、下記のようにスクリプトを作成しました ago7.vbs --------------------------- dim ago7d ago7d = dateadd("d", -7, now()) WScript.Quit(year(ago7d) & right(100 + month(ago7d),2) & right(100 + day(ago7d),2)) --------------------------- main.bat --------------------------- cscript //nologo ago7.vbs echo %ERRORLEVEL%>D:\log.txt --------------------------- ago7.vbsで7日前の日付を取得し、main.batで受け取り、テキストファイルに出力しています。 こちらをコマンドプロンプトから直接「main.bat」を起動してやると正しく動作しますが、 (この場合のlog.txtは 20120903tが書き込まれて出力されています。) タスクスケジューラを使ってmain.batを実行すると、log.txtの新居陽は下記のようになってしまいます。 ECHO は <ON> です。 いろいろ試してみていますがうまくいきません。 どのようにすればlog.txtの内容が日付になるのでしょうか。

  • DOSバッチでUNIXテキストファイルの文字列置換

    お世話になります。 早速ですが、 「DOSバッチでテキストファイルの文字列置換を行うプログラム」がいろいろ紹介されていたので、 皆さんのプログラムを流用させていただき、勝手に継ぎ足したDOSバッチプログラムを以下の ように作りました。 このDOSバッチで置換されたテキストファイルに2つの問題が発生して困っています。 問題 1)UNIXテキストファイルの改行コードがLFからCR+LFに変ってしまう。     文字列置換した後にファイルサイズが大きくなっていたので発見しました。      問題 2)空白行がなくなる。     DOSプログラムでは、対応不可でしょうか?     やはり、sed,awk,WHS,power shell を使わないと解決しませんか? -(DOSプログラム f0.bat)------------------------------------------------------ ::** @echo off setlocal ENABLEDELAYEDEXPANSION set fname=%1 copy /b %fname% org >nul type nul >%fname% for /f "delims=" %%a in (org) do (set line=%%a&&set l=!line:abc=xxx!&&echo !l!>>%fname%) del org goto end :end exit /b 0 -(実行時の標準出力結果 list)----------------------------------------------- C:\>setlocal ENABLEDELAYEDEXPANSION C:\>set fname=t22.txt C:\>copy /b t22.txt org 1>nul C:\>type nul 1>t22.txt C:\>for /F "delims=" %a in (org) do (set line=%a && set l=!line:abc=xxx! && echo !l! 1>>t22.txt ) C:\>(set line=J0000000 && set l=!line:abc=xxx! && echo !l! 1>>t22.txt ) C:\>(set line=HHH && set l=!line:abc=xxx! && echo !l! 1>>t22.txt ) C:\>(set line=519 && set l=!line:abc=xxx! && echo !l! 1>>t22.txt ) C:\>(set line=2011-08-28 12:16:44.98302 && set l=!line:abc=xxx! && echo !l! 1>>t22.txt ) C:\>(set line=2011-08-28 12:16:44.016114 && set l=!line:abc=xxx! && echo !l! 1>>t22.txt ) C:\>(set line=0 && set l=!line:abc=xxx! && echo !l! 1>>t22.txt ) C:\>(set line=abc && set l=!line:abc=xxx! && echo !l! 1>>t22.txt ) C:\>del org C:\>goto end C:\>exit /b 0 --(置換前 t22.org LF改行コード)-------------- J0000000 HHH 519 2011-08-28 12:16:44.98302 2011-08-28 12:16:44.016114 0 abc --(置換後 t22.txt CR+LF改行コード)----------- J0000000 HHH 519 2011-08-28 12:16:44.98302 2011-08-28 12:16:44.016114 0 xxxx ------------------------------------------ 皆さんのご意見、ご指導をお待ちしてます。

  • バッチファイルについて

    バッチファイルについて バッチファイルの勉強をしておりますが、以下のバッチで 分からない箇所があります。 @echo off copy C:\bin\set.txt set.txt | find /v "コピー" echo ユーザー名を入力してください echo 入力後、Ctrlキーを押しながらZキーを押した後、Enterキー copy con inp.txt | find /v "コピー" copy set.txt+inp.txt setinp.bat | find "○○" call setinp.bat echo ユーザー名は%INP%と入力されました! del setinp.bat set.txt inp.txt <<不明箇所>> まず、C:\bin\set.txt』は set INP= とだけ書いたファイルです。 copy C:\bin\set.txt set.txt | find /v "コピー" ですが、|find /v"コピー"はなんのためにやっているのでしょうか?? find /vを調べてみると、指定した文字列を含まない行の内容をすべて画面に表示します。 と記載されていますが・・・・このバッチでは一体なぜ最初にいるのでしょう?? copy con inp.txt | find /v "コピー" ですが、コンソールから入力させた文字列をinp.txtに保存しているらしいのですが、 そのあとに、また、|find /v"コピー"がでてきますが、なぜでしょう??なにを したいのでしょう?? さらにまた、copy set.txt+inp.txt setinp.bat | find "○○"が出てきますが、 ここでなぜまた意味不明な、|find"○○"がでてくるのでしょう?? さらにさらに、バッチを実行してみると、set.txtの中身にはコンソールから 入力した文字は何も記載されていない、そして、inp.txtやsetinp.txtという テキストファイルも、どのフォルダにも出来ていません。 最後の行のdel setinp.bat set.txt inp.txtを消して実行してみても同じです。 なぜでしょう?? このバッチの動き、例としての意図が全く分かりません。。。。 この例題が悪すぎるのか、私の頭がわるすぎるのか・・・・ ちなみに、上記バッチは、http://www.geocities.co.jp/SiliconValley-SanJose/1227/batinput.html のサイトのものです。 どなたかご教授願います。。。一週間悩みましたが、まったく理解できない状態です。。。

  • バッチファイル(.bat)へWSH(.wsf)のエラーコードの返し方について

    はじめまして、kiwi88と申します。 バッチファイル(.bat)からwshスクリプト(.wsf)を呼び出すプログラムを作成しました。 そこで、wshスクリプトで実行されたエラーコードを呼び出しもとのバッチファイル(.bat)に返すことはできますでしょうか。 以下はバッチファイル(.bat)からwshスクリプト(.wsf)を呼び出す箇所のソースです。 ◆バッチファイル(test.bat)◆ ---------------------------------------- ~※処理内容省略~ cscript test.wsf //nologo //Job:wshscript > batch.log IF %ERRORLEVEL% NEQ 0 GOTO ERR exit :ERR set ret=%ERRORLEVEL% echo ****** [%:ERRORLEVEL=%ret%] ****** > err.txt exit %ret% ---------------------------------------- 以下はwshスクリプト(.wsf)のエラーコードを返す箇所のソースです。 ◆wshスクリプト(test.wsf)◆ ---------------------------------------- <job id = "wshscript"> <script language = "VBScript"> <![CDATA[ Option Explicit Function Main() ~※処理内容省略~ err = Err.Number Main = err End Function ]]> </script> </job> ---------------------------------------- 長くなってしまい、申し訳ありませんが、 ご教授願えますでしょうか。 宜しくお願いいたします。

専門家に質問してみよう