底辺でもがくITエンジニア
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
windowsにはコマンドと呼ばれるCUIを用いて処理を行うファイル(バッチファイル)を作成することが出来ます。
今回のお話は初心者向けではなくある程度バッチファイルの作成が出来る方、タイトルでお悩みの方がいれば参考にしていただければと思います。
2009年02月22日修正
今回のお話は初心者向けではなくある程度バッチファイルの作成が出来る方、タイトルでお悩みの方がいれば参考にしていただければと思います。
2009年02月22日修正
さて、コマンドや簡単なスクリプトに限らず、処理を走らせた後はその結果を変数に返すと言うことがコンピュータの世界では暗黙の了承となっています。
戻り値なんていいますが、ググると若干意味が異なりますのでここでは戻り値、リターンコードとは終了コードと同一の扱いでお話します。
バッチファイルにおいて戻り値を返すにはバッチファイル終了コマンド(普通にファイルの最後まで処理が走れば自動で終了しますが、ここでは明示的に処理を終わらせた場合です)である”EXIT”にオプション”/B”をつけた上で引数に数値を渡します。
数値はいくつでも良いですが(言語によって変わる為、ここではいくつでも良いと記載します)、普通は2桁に収めます。
と、言うより3桁必要なことはほとんど無いでしょう。
またバッチファイルの走行後自動でプロンプトも終了し、通常は戻り値は回収できません。
ですので必要なのはサブバッチ、つまりバッチからバッチを呼んだ場合です。
a.batの処理でb.batの処理が必要なため内部で呼び出した後、b.batの処理が終了しb.batが正常終了した場合にa.batは残りの処理を走らせたい場合a.batはb.batの処理の結果を必要とします。
こうした場合の正常/異常を数値としてa.batに返してあげるのです。
まさに「戻り値」ですね。
で、この戻り値なのですが、想定どおりに値を返してくれない場合があります。
それが即時展開のトラップです。
よく理解していないのですが、バッチファイルはバッチファイルを実行したときに全ての変数を即時展開するらしいです。
その為、FOR文の中で値を動的に変えてもすでに展開済みの変数に関しては再設定が出来ないというもの(っぽいです)。
これを避けるために変数の即時展開を遅延展開させます。
これを遅延環境変数というらしいです。
リンク先の通りなのですが、なるべくバッチの冒頭にSETLOCALコマンドを使い対象変数を「%%」から「!!」に変えて展開するだけです。
なれないうちは全て「!!」で展開させたくなりますが、まずはデバッグしてみて怪しいと思ったら実行しつつ、慣れて行けばよいと思います。
まったく面倒なシステムですね・・・
で、この戻り値なんですが、規定どおりに指定してあげてもまれに、戻り値を返してくれません。
正確には返しているのだとは思いますが、子バッチを呼び出した親バッチは子バッチの戻り値を受け取れないことがあります。
因みにwindowsの場合戻り値はシステム変数"%ERRORLEVEL%"に格納されます。
そもそも変数に格納されないのですからやっぱりいろいろ考察すると戻り値自体を返していないのかもしれません。
とにもかくにもバッチからバッチを呼んでの処理を実施した場合、多くは呼ばれたバッチ(子バッチ)は何らかの形で処理の状況を呼び出し元(親バッチ)に知らせてあげないといけないケースは大半です。
そこで苦肉の策ですが、"EXIT"コマンド発行直前に戻り値となる予定の値をファイルとして出力してしまいます。
<<子バッチ>>
SET BATCHFILE_PATH="バッチファイルが格納されている任意のパス"
SET RC_PATH=%BATCHFILE_PATH%\tmp\returncode\
ECHO. > "%RC_PATH%"\0
EXIT/B 0
<<親バッチ>>
SET BATCHFILE_PATH="バッチファイルが格納されている任意のパス"
SET RC_PATH="%BATCHFILE_PATH%"\tmp\returncode\
IF EXIST "%RC_PATH%"\0 ( ECHO 子バッチは正常終了です )
上記のようにすればとりあえずは戻り値の代替として使用できます。
因みに戻り値が取得できないのはFOR文の中でサブバッチを呼んだりするケースが臭いです。
尚、環境変数の引継ぎに関しては"CALL"で呼んであげれば引き継がれるはずなんですが、当事象は環境変数も引き継げません。
さまざまな要因が考えられるでしょうが、当該事象を経験で解決策をご存知の方はコメントいただけるとありがたいです。
同事象でここにたどり着いた方は上記の方法を提案します。
再現ですが、下記環境でデバッグを行っています。
OS:windows 2003 server enterprise edition R2 (実機及び仮想端末上)
タイプ:*.bat
子バッチの呼び出し方法: CALL
呼び出したときの処理:FOR文内
※文中の文言はかなり砕けた表現を使っています。
当たらずとも遠からずな文言は無視してください、細部にわたる突っ込みは荒らしとみなします。
明らかに間違った表現はご指摘ください。
文中の""括りはコマンドを示唆します、実際の使用には""ははずしてください。
例文の中の""括りは場合によっては必要あるいは必須です。
例文の日本語文字は"REM"にてコメントアウトしていない場合適切に読み替えてください
戻り値なんていいますが、ググると若干意味が異なりますのでここでは戻り値、リターンコードとは終了コードと同一の扱いでお話します。
バッチファイルにおいて戻り値を返すにはバッチファイル終了コマンド(普通にファイルの最後まで処理が走れば自動で終了しますが、ここでは明示的に処理を終わらせた場合です)である”EXIT”にオプション”/B”をつけた上で引数に数値を渡します。
数値はいくつでも良いですが(言語によって変わる為、ここではいくつでも良いと記載します)、普通は2桁に収めます。
と、言うより3桁必要なことはほとんど無いでしょう。
またバッチファイルの走行後自動でプロンプトも終了し、通常は戻り値は回収できません。
ですので必要なのはサブバッチ、つまりバッチからバッチを呼んだ場合です。
a.batの処理でb.batの処理が必要なため内部で呼び出した後、b.batの処理が終了しb.batが正常終了した場合にa.batは残りの処理を走らせたい場合a.batはb.batの処理の結果を必要とします。
こうした場合の正常/異常を数値としてa.batに返してあげるのです。
まさに「戻り値」ですね。
で、この戻り値なのですが、想定どおりに値を返してくれない場合があります。
それが即時展開のトラップです。
よく理解していないのですが、バッチファイルはバッチファイルを実行したときに全ての変数を即時展開するらしいです。
その為、FOR文の中で値を動的に変えてもすでに展開済みの変数に関しては再設定が出来ないというもの(っぽいです)。
これを避けるために変数の即時展開を遅延展開させます。
これを遅延環境変数というらしいです。
リンク先の通りなのですが、なるべくバッチの冒頭にSETLOCALコマンドを使い対象変数を「%%」から「!!」に変えて展開するだけです。
なれないうちは全て「!!」で展開させたくなりますが、まずはデバッグしてみて怪しいと思ったら実行しつつ、慣れて行けばよいと思います。
まったく面倒なシステムですね・・・
正確には返しているのだとは思いますが、子バッチを呼び出した親バッチは子バッチの戻り値を受け取れないことがあります。
因みにwindowsの場合戻り値はシステム変数"%ERRORLEVEL%"に格納されます。
そもそも変数に格納されないのですからやっぱりいろいろ考察すると戻り値自体を返していないのかもしれません。
とにもかくにもバッチからバッチを呼んでの処理を実施した場合、多くは呼ばれたバッチ(子バッチ)は何らかの形で処理の状況を呼び出し元(親バッチ)に知らせてあげないといけないケースは大半です。
そこで苦肉の策ですが、"EXIT"コマンド発行直前に戻り値となる予定の値をファイルとして出力してしまいます。
<<子バッチ>>
SET BATCHFILE_PATH="バッチファイルが格納されている任意のパス"
SET RC_PATH=%BATCHFILE_PATH%\tmp\returncode\
ECHO. > "%RC_PATH%"\0
EXIT/B 0
<<親バッチ>>
SET BATCHFILE_PATH="バッチファイルが格納されている任意のパス"
SET RC_PATH="%BATCHFILE_PATH%"\tmp\returncode\
IF EXIST "%RC_PATH%"\0 ( ECHO 子バッチは正常終了です )
上記のようにすればとりあえずは戻り値の代替として使用できます。
因みに戻り値が取得できないのはFOR文の中でサブバッチを呼んだりするケースが臭いです。
尚、環境変数の引継ぎに関しては"CALL"で呼んであげれば引き継がれるはずなんですが、当事象は環境変数も引き継げません。
さまざまな要因が考えられるでしょうが、当該事象を経験で解決策をご存知の方はコメントいただけるとありがたいです。
同事象でここにたどり着いた方は上記の方法を提案します。
再現ですが、下記環境でデバッグを行っています。
OS:windows 2003 server enterprise edition R2 (実機及び仮想端末上)
タイプ:*.bat
子バッチの呼び出し方法: CALL
呼び出したときの処理:FOR文内
※文中の文言はかなり砕けた表現を使っています。
当たらずとも遠からずな文言は無視してください、細部にわたる突っ込みは荒らしとみなします。
明らかに間違った表現はご指摘ください。
文中の""括りはコマンドを示唆します、実際の使用には""ははずしてください。
例文の中の""括りは場合によっては必要あるいは必須です。
例文の日本語文字は"REM"にてコメントアウトしていない場合適切に読み替えてください
PR
この記事にコメントする