This batch detects the caller name script or even if it is called directly from the command line
@echo off setlocal DisableDelayedExpansion set "func=%~0" for /F "delims=\" %%X in ("%func:*\=%") do set "func=%%X" if ":" == "%func:~0,1%" ( goto %func% ) REM *** Get the name of the caller ( (goto) 2>nul setlocal DisableDelayedExpansion call set "caller=%%~f0" call set _caller=%%caller:*%%~f0=%% if defined _caller ( set "callType=batch" call "%~d0\:mainFunc\..%~pnx0" %* ) ELSE ( set "callType=cmd-line" cmd /c "call "%~d0\:mainFunc\..%~pnx0" %*" ) endlocal ) echo NEVER REACHED exit /b :mainFunc echo :mainFunc of %~nx0 arg1=%1 is called from '%caller%'/%callType% exit /b
It exploits the fact that the (goto)
operator will remove one level from the stack.
This leads to the exit from the current batch file, and %~f0
will be the name of the calling script (and %~0
current function of this batch) or the text %~f0
if called from the command line.
Then the native script is called again with "%~d0\:mainFunc\..%~pnx0"
External script
For ease of use, you can add an auxiliary batch file.
Use it in your scripts with this line
@echo off <:GetCaller <nul call GetCaller.bat myCallerVar echo This batch was called from "%myCallerVar%"
Name the helper batch file GetCaller.bat
@echo off setlocal DisableDelayedExpansion set "func=%~0" for /F "delims=\" %%X in ("%func:*\=%") do set "func=%%X" if ":" == "%func:~0,1%" ( goto %func% ) REM *** STEP1 REM *** Get the filename of the caller of this script, needed for later restart that ( (goto) 2>nul setlocal DisableDelayedExpansion %= it could be reenabled by the GOTO =% set "_returnVar=%~1" call set "_lastCaller=%%~f0" call set "_argToLastCaller=%%*" call "%~d0\:Step2\..%~pnx0" %* ) exit /b %= This is never reached =% :Step2 REM *** STEP2 REM *** Get the filename/cmd-line of the caller of the script ( (goto) 2>nul (goto) 2>nul setlocal DisableDelayedExpansion %= it could be reenabled by the GOTO =% set "_returnVar=%_returnVar%" set "_lastCaller=%_lastCaller%" set "_argToLastCaller=%_argToLastCaller%" call set "caller=%%~f0" call set _caller=%%caller:*%%~f0=%% if defined _caller ( set "callType=batch" call "%~d0\:Step3batch\..%~pnx0" ) ELSE ( set "callType=cmd-line" cmd /c "call "%~d0\:Step3batch\..%~pnx0" " ) endlocal ) exit /b %= This is never reached =% :Step3batch REM *** STEP3 Restart the requester batch, but jump to the label :GetCaller call :GetCaller exit /b %= This is never reached =% :GetCaller REM *** This uses the trick, that starting a batch without CALL will jump to the last used label if "%_returnVar%" NEQ "" set "%_returnVar%=%_caller%" %_lastCaller% %_argToLastCaller% echo
source share