くろねこ自由気ままな日記

趣味の話題や忘備録(的な)情報のページ

ブログランキング・にほんブログ村へ

第5回 バッチ特集 ~CALL~


おはようございます。くろねこです。

バッチ特集」の 第5回 です。

今回の記事は、CALL についてです。

 

【ご注意】
本サイトを参考に作成したものは、自己責任でお願いします。
実行前のレビューやテストを必ず実施してください。

それでは、今回もよろしくお願いします。

CALLとは【講釈】

バッチのCALLは、一般的なプログラム言語のCALLとほぼ同じものと考えてください。
CALLは以下の二つのことができます。
・ 別のバッチファイルを呼び出す
・ バッチファイル内の一部をサブルーチンとして呼び出す

別のバッチを呼び出す【講釈】

呼び出し方法は以下の通りです。

    call バッチファイル

呼び出すバッチファイルが別のフォルダに存在する場合は、そのパス名も含めて記述します。

呼び出したバッチの実行が終了するとCALLの次の命令が実行されます。

呼び出したバッチの終了コードも判断することができます。
終了コードは、ERRORLEVEL で判断します。

もう少し、掘り下げていきましょう!

呼び出し方法はほかにも

同期型(※)でのバッチの呼び出し方法は
① CALL
② START "" /WAIT /B
③ CMD /C
の何れの方法でも可能です。

※ 同期型とは、親プロセスが子プロセスを呼び出した際に、親プロセスは子プロセスの終了を待ちます。

これら3つの方法について、Windows11の環境での検証を実施しました。


呼び出し方法の比較

あくまでも個人的な感想ですが、
やはり、扱いやすさからして、おすすめは、CALLですね。
シンプルですし、システムへの負荷も少ない(新たなプロセスを生成しない)のが
モア ベター  おばちゃまぁ~(古)

そもそも、STARTコマンドは本来、非同期実行を目的としたものですので、同期実行させるのには、ちょっと手間がかかるのかもしれません。

サブルーチン【講釈】

CALLのもう一つの使い方として、バッチ内の一部をサブルーチン化することができます。
具体的には、バッチ内に記述したラベルをCALLで呼び出すことができます。

ざっくりですが、こんな感じです。

    ・・・
    call :ラベル
    ・・・
    exit /b
:ラベル
    (サブルーチンでの処理)
    exit /b

サブルーチン化のメリットは
同じような処理をバッチ内の複数の個所で組む場合は、その処理をサブルーチンとして作成し、呼び出したほうが効率的になります。

サンプル

別のバッチ呼び出し (CALL)

@echo off
rem *** Main.bat ***
    cd /d %~dp0
    echo Main.bat Started %date% %time%
    echo CALL呼び出し 第1引数と第2引数をSub.batに渡します。
    call .\Sub.bat %1 %2
    echo Sub.bat 終了コード : %ERRORLEVEL%
    echo Main.bat Ended %date% %time%
    exit /b

上記のバッチを Main.bat で保存してください。
(※文字コードANSIです)

@echo off
rem *** Sub.bat ***
    cd /d %~dp0
    echo Sub.bat  Started %date% %time%
    echo 第1引数 : %1
    echo 第2引数 : %2
    pause
    echo Sub.bat  Ended %date% %time%
rem 終了コードは無条件に 16 とします
    exit /b 16

上記のバッチを Sub.bat で保存してください。保存先は Main.bat と同じフォルダです。
(※文字コードANSIです)

コマンドプロンプトを開き、保存先フォルダをカレントフォルダにして、Main.bat を実行してみてください。
以下のように実行されます。


実行結果(CALL)

別のバッチ呼び出し (START)

STARTコマンドで バッチの CALL と同じ動きをさせるための方法です。
個人的な意見ですが、
STARTコマンドの(変な)仕様のため、使い方に注意が必要です。

【呼び出し元】

呼び出し元(main.bat)では、

    start "" /wait /b 呼び出すバッチ [引数1 [引数2 ・・・]]

と書きます。
最初の "" はタイトル(コマンドプロンプトのタイトルバーに表示されるもの)で、省略した場合、呼び出すバッチが "" で囲まれているときに誤認するので、タイトル不要でも必ず書いた方がよいです。

/wait /b は必ず指定します。
/wait は、同期型実行で、呼び出し先の処理が終了するまで処理の実行を待ちます。
/b は、新しいウィンドウを作成せずに、呼び出し先の処理を実行します。

【呼び出し先】

呼び出し先(sub.bat)では、終了時に

    exit [終了コード]

と書きます。
/b を付けると呼び出し元のバッチも一緒に終了します。

以下、サンプルです。

@echo off
rem *** Main.bat ***
    cd /d %~dp0
    echo Main.bat Started %date% %time%
    echo START /WAIT 呼び出し 第1引数と第2引数をSub.batに渡します。
    start "" /wait /b .\Sub.bat %1 %2
    echo Sub.bat 終了コード : %ERRORLEVEL%
    echo Main.bat Ended %date% %time%
    exit /b

上記のバッチを Main.bat で保存してください。
(※文字コードANSIです)

@echo off
rem *** Sub.bat ***
    cd /d %~dp0
    echo Sub.bat  Started %date% %time%
    echo 第1引数 : %1
    echo 第2引数 : %2
    pause
    echo Sub.bat  Ended %date% %time%
rem 終了コードは無条件に 32 とします
    exit 32

上記のバッチを Sub.bat で保存してください。保存先は Main.bat と同じフォルダです。
(※文字コードANSIです)

コマンドプロンプトを開き、保存先フォルダをカレントフォルダにして、Main.bat を実行してみてください。
以下のように実行されます。


実行結果(START)

別のバッチ呼び出し (CMD)

CMDコマンドで バッチの CALL と同じ動きをさせるための方法です。

【呼び出し元】

呼び出し元(main.bat)では、

    cmd /c 呼び出すバッチ [引数1 [引数2 ・・・]]

と書きます。

【呼び出し先】

呼び出し先(sub.bat)では、終了時に

    exit [/b] [終了コード]

と書きます。
/b は書いても省略しても同じ動きをします。

以下、サンプルです。

@echo off
rem *** Main.bat ***
    cd /d %~dp0
    echo Main.bat Started %date% %time%
    echo CMD /C 呼び出し 第1引数と第2引数をSub.batに渡します。
    cmd /c .\Sub.bat %1 %2
    echo Sub.bat 終了コード : %ERRORLEVEL%
    echo Main.bat Ended %date% %time%
    exit /b

上記のバッチを Main.bat で保存してください。
(※文字コードANSIです)

@echo off
rem *** Sub.bat ***
    cd /d %~dp0
    echo Sub.bat  Started %date% %time%
    echo 第1引数 : %1
    echo 第2引数 : %2
    pause
    echo Sub.bat  Ended %date% %time%
rem 終了コードは無条件に 64 とします
rem    exit 64
    exit /b 64

上記のバッチを Sub.bat で保存してください。保存先は Main.bat と同じフォルダです。
(※文字コードANSIです)

コマンドプロンプトを開き、保存先フォルダをカレントフォルダにして、Main.bat を実行してみてください。
以下のように実行されます。


実行結果(CMD)

サブルーチン呼び出し (基本形)

バッチの一部をサブルーチンとして利用する場合は以下のようにバッチを作ります。

    ・・・
    call :ラベル [引数1 [引数2 ・・・]]
    (errorlevelで終了コードを取得)
    ・・・
    exit /b [メインの終了コード]

:ラベル
    (サブルーチンの処理)
    exit /b [サブルーチンの終了コード]

サブルーチンで引数を受け取る場合は、%1、%2・・・とバッチの引数と同じように受け取ることができます。
呼び出し元(メインルーチン)の引数とサブルーチンの引数は同じ %1 ・・・ と表現しますが、
それぞれの変数の領域は異なるものですので
・ メインルーチンの%1
・ サブルーチンの%1
という風に考えてください。

サブルーチンの終了部分はバッチ同様に exit で終了コードを呼び出し元に返すことができます。

以下、サンプルです。

@echo off
rem *** Main.bat ***
    cd /d %~dp0
    echo Main.bat Started %date% %time%
    echo 第1引数 : %1
    echo 第2引数 : %2
    echo サブルーチン呼び出し 第1引数と第2引数を加算した結果を引数にします。
    set /a @param=%1+%2
    call :sub %@param%
    echo サブルーチンの終了コード : %ERRORLEVEL%
    echo 第1引数 : %1
    echo 第2引数 : %2
    echo Main.bat Ended %date% %time%
    exit /b

:sub
rem *** Subroutine ***
    echo Subroutine  Started %date% %time%
    echo 第1引数 : %1
    echo 第2引数 : %2
    echo 第1引数の数値を 10倍して戻り値とします。
    pause
    set /a @ans=%1*10
    echo Subroutine Ended %date% %time%
    exit /b %@ans%

上記のバッチを Main.bat で保存してください。
(※文字コードANSIです)

コマンドプロンプトを開き、保存先フォルダをカレントフォルダにして、Main.bat を実行してみてください。(引数1=10、引数2=5)
以下のように実行されます。


実行結果(基本形)

サブルーチン呼び出し (ちょっと応用:引数分解)

呼び出し元(メインルーチン)から、サブルーチンを呼び出す際にスペースを含んだ文字列を指定すると スペースで分離された文字列がサブルーチンに渡されます。
(まあ、あたりまえですね)

以下、サンプルです。

@echo off
rem *** Main.bat ***
    cd /d %~dp0
    echo Main.bat Started %date% %time%

    set @string=abcd 1234 efgh 5678
    echo サブルーチン呼び出し スペースを含んだ文字列を引数にします。
    call :sub %@string%
    echo サブルーチンの終了コード : %ERRORLEVEL%
    echo Main.bat Ended %date% %time%
    exit /b

:sub
rem *** Subroutine ***
    echo Subroutine  Started %date% %time%
    echo 第1引数 : %1
    echo 第2引数 : %2
    echo 第3引数 : %3
    echo 第4引数 : %4
    pause
    echo Subroutine Ended %date% %time%
    exit /b 0

上記のバッチを Main.bat で保存してください。
(※文字コードANSIです)

コマンドプロンプトを開き、保存先フォルダをカレントフォルダにして、Main.bat を実行してみてください。(引数1=10、引数2=5)
以下のように実行されます。


実行結果(引数分解)

おわりに

なかなか説明が難しく、全体的に講釈っぽくなってしまいました。すいません。
バッチを作成した方なら、サンプル部分を見ていただくことで、動きが理解できると思います。
念のため、これらのサンプルはWindows11で検証したものです。
まだまだ、バグが多いWindows11ですが、バッチは何とか動くようです(笑)

それでは

 


くろねこ自由気ままな日記

バッチ特集の過去の記事は下記をクリック願います。

 

 www.kuronekofreedom.com

ブログランキング・にほんブログ村へ
© 2020 くろねこ自由気ままな日記