Windowsコマンドプロンプトでのエラーメッセージとヘルプメッセージのカスタマイズ方法で重要なのは、実行例を増やすことより、対象と戻し方を先に確定することです。結論は「helpはusageとoptionをstdoutへ、errorは1>&2でstderrへ出し、exit /bで意味のあるnonzero codeを返します。利用者入力を未quotedのif数値比較へ渡さず、存在・形式を先に検証します。」。ここではWindows cmd.exe batch fileで、message表示とmachine-readable exit codeを分ける条件を前提に、2026年7月17日時点の公式仕様から、現場で再現できる判断順を組み立てます。 確認ポイント:stdout、stderr、終了codeは互いに独立したcaller向けAPI契約として検証します。
stdout・stderr・終了codeの契約を先に決める
echo、stderr redirect、exit /b、callの入力、出力、変更有無を一文で書き、host、user、current directory、実行時刻を添えます。版が違う端末の結果を混ぜず、同じ条件のsampleで再現してから対象を広げます。
- cmd /?と各command /?でsyntaxを確認する
- 必須argument、optional switch、exit code表を決める
- stdout/stderrを受けるschedulerやcaller仕様を確認する
- messageにsecretやuser入力全文を含めない
help・入力error・正常終了をbatchで実装する
usage labelは終了code 0で返す
@echo off
if /i "%~1"=="/?" goto :help
if /i "%~1"=="--help" goto :help
goto :main
:help
echo Usage: %~nx0 INPUT_FILE [/quiet]
echo INPUT_FILE Readable input file
exit /b 0
%~nx0でbatch名を表示します。helpは成功code 0です。
必須argument不足をstderrへ出す
if "%~1"=="" (
>&2 echo ERROR: INPUT_FILE is required.
>&2 echo Run %~nx0 --help for usage.
exit /b 2
)
error messageをstderr、usage errorを2と定義します。
入力file不存在へ専用codeを割り当てる
if not exist "%~1" (
>&2 echo ERROR: Input file was not found.
exit /b 3
)
path全文の外部log公開は避けます。
subroutineのERRORLEVELを直後に返す
call :validate "%~1"
if errorlevel 1 exit /b %errorlevel%
echo Validation passed.
exit /b 0
:validate
if not exist "%~1" exit /b 3
exit /b 0
if errorlevel nは以上判定なので順序に注意します。
呼出側で二つのstreamを別logへ保存する
tool.cmd input.txt 1>output.log 2>error.log
echo ExitCode=%errorlevel%
同じfileを入力と出力に使いません。log ACLと保持期間を設定します。
表示文ではなくERRORLEVELをmachine判定に使う
echoされたERROR文字列だけではcallerが機械判定できないためexit codeを契約にします。exitはcmd windowを閉じる場合があるのでbatch内はexit /bです。if errorlevel 1は1以上を意味します。set /pへ任意入力を受けてlss比較するとsyntax errorやmetacharacter injectionを招くため、argument formatを限定します。
message変更前にcallerとの互換性を確認する
user入力を未quotedでcommandへ展開せず、&、|、<、>等を含む値をeval的に扱いません。secretをechoやerror logへ出しません。既存logへ無期限appendせず新規run IDとrotationを使います。message変更前にcallerが依存するexit codeをtestし、問題時はversion管理から旧batchへ戻します。
if errorlevelの以上判定を誤読しない
- errorをstdoutだけへ出す
- exitで親cmdを閉じる
- if errorlevelを等価比較と思う
- set /p入力を未検証で数値比較する
- message文言だけをmachine判定に使う
help・usage error・正常系を一式で検証する
help、必須欠落、fileなし、正常、space入りpath、metacharacterを含む安全なsampleでstdout、stderr、exit codeを確認します。schedulerやPowerShell callerからもcodeを受け取り、version管理diffとrollbackをtestします。
cmd batchのerror/help message設計を定期化するなら、正常件数、警告境界、停止条件を数値化します。
cmd message設計の合格基準
batch messageは通常結果をstdout、利用者が直す入力errorをstderrへ出し、成功0・usage 2・fileなし3等の終了codeを契約として固定します。subroutineはexit /b codeで返し、呼出側がERRORLEVELを直後に保存します。
stdoutとstderrを分ける完成batch
@echo off
if "%~1"=="" (>&2 echo USAGE: %~nx0 input-file & exit /b 2)
if not exist "%~1" (>&2 echo NOT_FOUND: %~1 & exit /b 3)
echo OK: %~f1
exit /b 0
このcodeは画面表示だけを見るための例ではありません。通常系では「成功messageがstdoutだけに出てERRORLEVEL 0になる」を確認し、0件と実行errorを別の結果として保存します。
成功・利用者error・内部errorを分類する
- 期待どおり:成功messageがstdoutだけに出てERRORLEVEL 0になる
- 0件・非適用:必須argumentなしはusageをstderrへ出しcode 2、fileなしはcode 3になる
- 実行error:内部command失敗はそのcodeを上書きせず文脈messageとともに返す
echo後の別commandでERRORLEVELを上書きしないようset rc=%ERRORLEVEL%を直後に置きます。日本語messageのencodingをconsumerと合わせ、errorをstdoutへ混ぜてparserを壊しません。括弧block内の%ERRORLEVEL%展開時点にも注意します。
argumentなし・fileなし・空白pathを試す
tool.cmd 1>out.txt 2>err.txt
set "usage_rc=%ERRORLEVEL%"
echo usage_rc=%usage_rc%
tool.cmd missing.txt 1>out.txt 2>err.txt
set "missing_rc=%ERRORLEVEL%"
echo missing_rc=%missing_rc%
success、argumentなし、fileなし、path空白、内部command errorをtestします。stdout/stderr内容、code、message encoding、呼出側の分岐をgolden fileと比較します。
Windowsコマンドプロンプトでのエラーメッセージとヘルプメッセージのカスタマイズ方法の証跡には、実行対象と取得時刻に加え、通常・0件・errorのどれへ分類したかを残します。通常系は「成功messageがstdoutだけに出てERRORLEVEL 0になる」、停止系は「内部command失敗はそのcodeを上書きせず文脈messageとともに返す」を判断文としてそのまま作業票へ写し、担当者ごとの言い換えで意味が変わらないようにします。
batch fileをCIで反復確認する場合は、stdout、stderr、終了codeを別fileへ捕捉し、同じrun IDでgolden dataと比較します。code pageと呼出し元shellをmanifestへ残し、表示文の一致だけで成功にしません。ERRORLEVELは別commandを挟む前に保存し、診断文の変更が呼出側の分岐を壊す場合は互換性変更としてreviewへ回します。

コメント