ひがきの日記

2009-08-14

コマンドの終了ステータスが取れない

errorlevel

コマンドプロンプトからコマンドを実行すると、成功したか失敗したかが数値で返ってくる。

その値は errorlevel で見ることができる。

C:\> dir
    ...
C:\> echo %errorlevel%
0

C:\> dirr
'dirr' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

C:\> echo %errorlevel%
9009

C:\>dir not.found
ファイルが見つかりません

C:\> echo %errorlevel%
1

errorlevel に代入してはいけない

この errorlevel は変数ではない。
間違って errorlevel に値を代入してしまうと、コマンド終了ステータスを見ることができなくなる。

C:\> set errorlevel=0

C:\> echo %errorlevel%
0

C:\> dirr
'dirr' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

C:\> echo %errorlevel%
0

errorlevel に値を代入すると、変数の errorlevel ができてしまって、本来の errorlevel にアクセスできないらしい。

errorlevel はエラーの重要度

DOS 用のコマンドを作るとき、

  • ファイルがないときは exit(2)
  • アクセス権がなければ exit(5)
  • etc.

などと設計するのは間違い。

コマンドの終了ステータスはエラーの種類ではなく、エラーの重要度。

C:\> dirr
'dirr' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

C:\> if errorlevel 3 echo NG
NG

C:\> dir not.found
ファイルが見つかりません

C:\> if errorlevel 3 echo NG

if errorlevel を使うと、指定した重要度以上のエラーを検知することができる。
if %errorlevel% == 3 とは違う。

if errorlevel は変数の errorlevel は見ないので、間違って値を代入しても正しく動く。

errorlevel が変化しない

ここからが本題。

コマンドを実行しても errorlevel が変化しなくてハマった。

VisualStudioデバッグウィンドウには
プログラム '……' はコード 100 (0x64) で終了しました。」
と表示されているのに、コマンドプロンプトから実行すると errorlevel が 0 のまま。

Cygwinbash から実行しても $? は 100 になるのに。なぜ?

ググッてググッてググりまくった結果、

コマンドプロンプトから実行してもセットされないのに、バッチファイルから実行したらセットされる。

と怒ってる人がいた。

まさかと思ってやってみた。

C:\> type wrap.bat
@echo off

%*
echo %errorlevel%

C:\> wrap foo.exe
100

できた。なぜ??

原因は分からないが、そういうもんらしい。

わざわざバッチファイルを作らなくても、これでイケるみたい。

C:\> cmd /C foo

C:\> echo %errorlevel%
100

2009-02-21

ECHO の不思議

これも昔書いた「Unix ユーザのための DOS FAQ

まず簡単なバッチファイルを作る。

ECHO foo
ECHO bar

それを実行すると、

DOS> foo.bat

DOS> ECHO foo
foo

DOS> ECHO bar
bar

DOS> _

いちいち実行するコマンドを表示してくれる。
プロンプトまで表示してくれる。

コマンドを非表示にするには @ を使う。

@ECHO foo
@ECHO bar

それを実行すると、

DOS> foo.bat
foo
bar

DOS> _

でも、全ての行に @ を付けるなんて、やってられない。

そういう時は ECHO OFF する。

@ECHO OFF
ECHO foo
ECHO bar

それを実行すると、

DOS> foo.bat
foo
bar

DOS> _

foo と bar の間に空行を入れてみる。

@ECHO OFF
ECHO foo
ECHO
ECHO bar

それを実行すると、

DOS> foo.bat
foo
ECHO は <OFF> です。
bar

DOS> _

ECHO に文字列を渡さないと、現在の状態 (ON または OFF) を教えてくれる。

空行を表示するには ECHO. を使う。

@ECHO OFF
ECHO foo
ECHO.
ECHO bar

それを実行すると、

DOS> foo.bat
foo

bar

DOS> _

ON または OFF という文字列を表示したいときも ECHO. を使う。

@ECHO OFF
ECHO.ON
ECHO.OFF

それを実行すると、

DOS> foo.bat
ON
OFF

DOS> _

なんでこんな仕様になっているのか?
不思議だ。

2009-02-13

プロンプトの変更

コマンドプロンプト (いわゆる DOS 窓) を起動すると、プロンプト*1が現われてコマンドを受け付ける。

C:\Documents and Settings\higaki>_

プロンプトにカレントディレクトリが表示されていて鬱陶しい。
変更したい。


プロンプトの変更

プロンプトは変数 prompt で変更できる。

C:\Documents and Settings\higaki>set prompt=foo:  ← 変更してみる。

foo:echo %prompt%  ← 変更できた。echo で確認。
foo:               ← 変数 prompt の中身。

foo:               ← プロンプト。

特殊文字

そのまま設定できない文字も以下の表記で設定できる。*2

$$
$ 記号
$A
&
$B
|
$C
(
$D
日付
$E
Enter
$F
)
$G
>
$I
非表示?
$L
<
$N
ドライブ
$P
カレントディレクトリのパス
$Q
=
$S
空白
$T
時刻
$V
バージョン
foo:set prompt=foo$G$S

foo> cd
C:\Documents and Settings\higaki

foo> _

これでスッキリ。

カレントディレクトリが分からなくなったら、引数なしで cd すればいい。

*1:ややこしいな

*2:ちなみにデフォルト値は "$P$G"