Is it possible to determine if a batch file is running with or without a CALL command?

The problem is that the CALL command doubles the caret sign ^ and makes a double percentage one . And in hybrid files this can be a big problem. Or if the bat fails with CALL from another bat, and you want to alert the user.

%cmdcmdline% (despite this, it can be used if the file is executed directly from the prompt) and (goto)>nul (in the end it can be used with this ). I think that is not useful here.

I still think about it, but if someone comes with an elegant solution, it will be great.

EDIT . one possible approach is to detect a batch recursive level , although a reliable way is needed to check this configuration record (I have no idea how it is calculated).

+8
batch-file
source share
5 answers

As in Jeb's answer, this cannot be different if the current batch file was called or if it was called directly from the called batch file. This code simply determines whether the execution context will ever be a batch file (there was a call somewhere to reach this point) or on the command line (there was no call , or the source context was the command line). Not the same, but maybe someone can get a better way from him.

edited after Jeb's comment. I, although echo could be more problematic, but it is not, so the approach (goto) is by far the best option.

 @echo off rem Check if this is the initial invocation or we have already determined rem how the batch file was started rem If already tested save method, remove test variable and goto main if defined __callTest__ ( set "startMethod=%__callTest__%" set "__callTest__=" goto :main ) rem Initial invocation - Test routine rem Cancel current batch context and check if the new context is rem - batch (there was a call somewhere) rem - command line (no call) rem Once the invocation method is determined, restart the current batch setlocal enableextensions disabledelayedexpansion call :getCurrentFile _f0 ( rem Cancel context 2>nul (goto) rem The context cancel operation interferes with echo logic. Restore echo on rem We try to read a non existing variable and see if we could. rem - In command line context, the reading of a non existing variable rem returns the name of the variable, setting our test var rem - In batch context, reading a non existing variable does not rem return anything, and the test variable is undefined call set "__callTest__=%%{[%random%""%random%]}%%" if defined __callTest__ ( set "__callTest__=direct" "%_f0%" %* ) else ( set "__callTest__=call" call "%_f0%" %* ) ) :getCurrentFile returnVar set "%~1=%~f0" goto :eof rem Main batch code :main setlocal enableextensions disabledelayedexpansion echo Method invocation is [ %startMethod% ] goto :eof 

And yes, of course, not bullet proof. This code has the usual problems handling arguments in the %* section.

+3
source share

As I understand your question, you need a method that allows the file.bat file file.bat determine whether it was called using the call command executed in another batch file or not, and the way to do this is to insert additional code verification in the batch file, correctly ?

Well, a very simple way to do this is to simply insert an extra line before the call command into the caller’s code to define the “call flag” variable. Thus, when such a variable is not defined in file.bat , it was not called through call :

In caller code:

 set "callFlag=1" call file.bat 

In file.bat file:

 if not defined callFlag echo Warning, I was not executed via CALL command! 
+4
source share

If I can understand your question: you need a method that allows the batch version of the script to determine if it was called using the call command from another batch of script. The following 33939966test.bat script shows a possible approach: force use with the required parameter "^%%%%" as follows:

 @ECHO OFF >NUL if "%~1" == "" goto :USAGE if "%~1" == "^^%%" echo call from another script %* & goto :GOOD if "%~1" == "^%%%%" echo from another script %* & goto :USAGE if "%~1" == "^^%%%%%%%%" echo call from command line %* & goto :USAGE if "%~1" == "^%%%%%%%%" echo from command line %* & goto :USAGE echo(wrong 1st parameter %%*=%* goto :USAGE :GOOD echo( rem echo original %%*=%* shift /1 rem echo shifted %%*=%* :: Note that `shift` does not affect %* ::::::::::::::::::::::::::::::::::::::: :: Useful code begins here goto :eof :USAGE echo USAGE: CALL %~nx0 "^%%%%%%%%" [parameters] echo( rem the 1st parameter must be: rem "CARET followed by four PERCENT SIGNS" including all " DOUBLE QUOTES goto :eof 

The output from the command line:

 ==> rem cmd copy&paste start ==> ECHO OFF >NUL 33939966test.bat "C&D pay 21 % VAT" "^=caret" %OS% %%OS%% wrong 1st parameter %*="C&D pay 21 % VAT" "^=caret" Windows_NT %Windows_NT% USAGE: CALL 33939966test.bat "^%%%%" [parameters] call 33939966test.bat "^%%%%" "C&D pay 21 % VAT" "^=caret" %OS% %%OS%% call from command line "^^%%%%" "C&D pay 21 % VAT" "^^=caret" Windows_NT %Windows_NT% USAGE: CALL 33939966test.bat "^%%%%" [parameters] 33939966test.bat "^%%%%" "C&D pay 21 % VAT" "^=caret" %OS% %%OS%% from command line "^%%%%" "C&D pay 21 % VAT" "^=caret" Windows_NT %Windows_NT% USAGE: CALL 33939966test.bat "^%%%%" [parameters] ECHO ON >NUL ==> rem cmd copy&paste end 

Conclusion from the caller:

 ==> 33939966myCaller.bat ==> call 33939966test.bat "C&D pay 21 %% VAT" "^=caret" Windows_NT %OS% wrong 1st parameter %*="C&D pay 21 % VAT" "^^=caret" Windows_NT Windows_NT USAGE: CALL 33939966test.bat "^%%%%" [parameters] ==> call 33939966test.bat "^%%" "C&D pay 21 %% VAT" "^=caret" Windows_NT %OS% call from another script "^^%" "C&D pay 21 % VAT" "^^=caret" Windows_NT Windows_NT ==> 33939966test.bat "^%%" "C&D pay 21 % VAT" "^=caret" Windows_NT %OS% from another script "^%%" "C&D pay 21 % VAT" "^=caret" Windows_NT %OS% USAGE: CALL 33939966test.bat "^%%%%" [parameters] 

where 33939966myCaller.bat reads as follows (copy and paste the paste):

 @ECHO ON call 33939966test.bat "C&D pay 21 %%%% VAT" "^=caret" %OS% %%OS%% @ECHO ON call 33939966test.bat "^%%%%" "C&D pay 21 %%%% VAT" "^=caret" %OS% %%OS%% @ECHO ON 33939966test.bat "^%%%%" "C&D pay 21 %% VAT" "^=caret" %OS% %%OS%% @ECHO OFF goto :eof rem cmd copy&paste start ECHO OFF >NUL 33939966test.bat "C&D pay 21 % VAT" "^=caret" %OS% %%OS%% call 33939966test.bat "^%%%%" "C&D pay 21 % VAT" "^=caret" %OS% %%OS%% 33939966test.bat "^%%%%" "C&D pay 21 % VAT" "^=caret" %OS% %%OS%% ECHO ON >NUL rem cmd copy&paste end 

Please note that the above approach is not bulletproof, as we can present a false result from the command line:

 ==> 33939966test.bat "^^%" "C&D pay 21 % VAT" "^=caret" %OS% %%OS%% call from another script "^^%" "C&D pay 21 % VAT" "^=caret" Windows_NT %Windows_NT% 

Perhaps combination of methods (goto) can help?

+4
source share

This can be done with some nasty tricks, so this is not an ideal solution .
I count how many calls are needed to get a stackoverflow, and then I compare the value with the value from the error output.

But you need to start the second cmd.exe process as stackoverflow kills the first instance of the instance

 @echo off setlocal EnableDelayedExpansion set "_fileCheck=%~0" if "!_fileCheck:~-4!"==".bAt" goto :child del stackoverflow.log start "" /b "%~dpn0.bAt" AllParameters set count=0 (call :recusion & echo NEVER) 1> stackoverflow.log 2>&1 echo #* NEVER exit /b :recusion set /a count+=1 echo +%count% call :recusion :child ping -n 2 localhost 2>&1 > nul :loop ( < stackoverflow.log ( rem dummy ) || goto :loop ) 2>nul :X for /F "tokens=1,2 delims=,=" %%L in ('type stackoverflow.log') do ( set "line=%%L" set "firstChar=!line:~0,1!" if "!firstChar!"=="+" ( set /a maxCount=!line! ) ELSE if "!firstChar!" NEQ "*" ( set /a overflow=%%M ) ) if !maxCount! EQU !overflow! ( echo Direct started ) ELSE ( echo CALL started ) exit 
+3
source share

Low-tech solution, just set and check the environment variable. So:

caller.cmd:

 SET calling=1 CALL called.cmd SET calling= 

called.cmd

 IF [%calling%]==[1] SET PATH=%PATH%;. 
+2
source share

All Articles