Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

can a .BAT file know the name of the .BAT file that called it?

Jul
207
6
A very meta situation.

Without changing the calling BAT file, I am wondering if the called BAT file can identify which BAT file called it.
 
I don't think the current version exposes the call stack to the user.

I imagine it would be possible to add, say, a %_calldepth variable and a %@callstack[n] function to make this info available. Whether there would be much call demand for such a feature, I have no idea.
 
There might be a clue in the environment. Or you could put one there.
 
I don't think the current version exposes the call stack to the user.

I imagine it would be possible to add, say, a %_calldepth variable and a %@callstack[n] function to make this info available. Whether there would be much call demand for such a feature, I have no idea.

I see what you did there with that 'call' joke! hehehe

Basically I've written something I can run after, well, any BAT, EXE, or internal command, that will check the error level, and pause if it's 1.

It sets a REDO flag that I can use in my calling script to redo after fixing whatever error conditions.

just in the name of helpful messaging, i wanted it to say which program was creating the errorlevel automatically, without having to add anything special from the calling script

Basically i'm adding this:
Code:
call errorlevel.bat
...after, well, almost everything now!

It's helping some of my workflows immensely. For instance giving me a chance to fix source code to deal with unexpected things, and the program just re-runs until i get my source code right and there's no errorlevel and it passes my errorlevel.bat

But yea, the minor cosmetic+convenience issue of being able to say "it was *this* script -- points to calling script -- who made the bad errorlevel" would be great.

I was thinking it was impossible without some sort of setup from the calling script, which I wanted to avoid, as I'm going to be pasting "call errorlevel.bat" into 100s of places in my BAT files in the future...
 
Wouldn't it be possible to add %_batchname to your call?

It's possible in the same way that hardcoding 250 unique values is possible, but it's not the preferred solution, in the same way that hardcoding something 250 times would not be the preferred solution to having a single dynamic value that works in all cases and is forever future-proof from clerical error.

This will come up at least 250 times for me personal. This will come up for everything I write for the rest of my life. Thus, I want to get it the perfect way I envision, but it's looking like that's not possible.

I'm just glad the errorlevel catcher i made works. I just wish I could make the most-informative-possible error message without hardcoding every call for the rest of my life - the return on that effort isn't worth it just to have a slightly more informative error message.
 
Last edited:
But damn would it be nice for my errorlevel-catcher script to be able to *automatically* say:

"This is the BAT file that called me and had a bad errorlevel! it is named THIS.BAT" and point directly to the culprit by explicit filename.
 
I don't think the current version exposes the call stack to the user.

I imagine it would be possible to add, say, a %_calldepth variable and a %@callstack[n] function to make this info available. Whether there would be much call demand for such a feature, I have no idea.

The existing _batch variable will return the batch nesting level.

Nobody has ever asked previously for the parent batch file name.
 
I'm honestly surprised nobody has asked, because it would be nice to pass error message handling to a script and have it say where the error message came from, without having to pass any parameters.

I would have thought it had come up in the 1990s! :) :) :) :)

I wish I'd participated in this forum a lot sooner!
 
It also seems like a neato security feature [that no one ever asked for] - you could force a BAT file to only be callable from another one by checking %_CALLINGFILE to see if it matches the one you intend your BAT file to be called from.

Admittedly at this point, I'm inventing more problems because I like the solution, and I'm sure there's other ways to do what I just said.
 
One of the nicest things about TCC is that you often can invent a missing feature. This is simple (and of possibly questionable robustness). It might be similar to what TCC might do internally.

Code:
v:\> alias call `set _callingfile=%@full[%%0] & *call`

v:\> type b1.btm
call b3.btm

v:\> type b2.btm
call b3.btm

v:\> type b3.btm
echo I am %@full[%0] and I was called by %_callingfile

v:\> b1.btm
I am V:\b3.btm and I was called by V:\b1.btm

v:\> b2.btm
I am V:\b3.btm and I was called by V:\b2.btm
 
Here's a "nested" test of the same alias.

Code:
v:\> type b1.btm
call b2.btm

v:\> type b2.btm
echo I am %@full[%0] and I was called by %_callingfile
call b3.btm

v:\> type b3.btm
echo I am %@full[%0] and I was called by %_callingfile

v:\> b1.btm
I am V:\b2.btm and I was called by V:\b1.btm
I am V:\b3.btm and I was called by V:\b2.btm
 
Is _CALLINGFILE restored when returning from a nested batch file?
That depends on SETLOCAL and I didn't like that. This alias works better but I'm not sure it's perfect.

Code:
alias call `setlocal & set _callingfile=%@full[%%0] & *call %$ & endlocal`
 
OMG. I redefine internal commands as aliases all the time***

What a great solution!!!!



*** (often to call a bat file that splits betwen cygwin and non-cygwin versions for machines of mine so that if they don't have cygwin they use the pre-cygwin fallback replacement utilities for common unix commands which i used to use in the pre-cygwin days) [yes, we're dug into the sand rather deep over here]


Side-rant:
And good to see setlocal used out of true necessity -- so often it is used out of a mere possibility of a duplicate environment variable name / namespace collision. And it's not a style I like because I often set variables as return values so I don't want setlocal enabled. But that approach can has it's own set of problems.
 
Well, SETLOCAL is rather heavy-handed; it does a lot. That's not an obvious problem but if I tried hard enough I could probably measure a performance hit.

Even if it were done internally ...

1. I reckon putting _CALLINGFILE in the environment is simply out because of nesting, SETLOCAL, and maybe other considerations.

2. With an internal _CALLINGFILE variable, TCC would have to have some mechanism for restoring its value when a CALLed BTM terminated and unsetting it when the top level BTM terminated. I don't know if there is such a mechanism. And I can't even guess whether that would be easy or hard.
 
Well, be careful what you wish for.

While this did solve the problem I was asking for, it apparently disrupts/destroys the %_? errorlevel variable.

You can see this in action - i have 2 python scripts that return 0 or 1, and i run my errorlevel catcher after both of them.

With the new alias, the errorlevel in errorlevel.bat is 0 but should be 1 after return-a-1.py

I'm trying to figure out a solution now. I just tried taking the setlocal/endlocal off but that wasn't the problem.




1685728671503.png
 
^ TL;'DR of the last comment is "now the receiving script has lost access to %_? to measure errorlevel"
 
I have no clue what you're doing but %? might be more appropriate than %_?.
 
SOLVED.

But alas, this doesn't actually work with setlocal if you want to also capture the errorlevel and convert that into an automatic variable and successfully reference those values from the called script.

Code:
call=`set _callingerrorlevel=%_? %+ set _callingfile=%@full[%%0] %+ *call %$`

I basically had to make a test suite (which also unaliased the command for a 2nd set of tests not pictured) and run it about 50 times to find the right combination that got the values passed successfully.

I FINALLY HAVE WHAT I WANT, THIS IS SO AWESOME.

Basically, i'm going to be able to just "call errorlevel" after anything i want caught.

It's going to make noticing errors and diagnosing broken workflows sooooooooooo much better!!



You can see the part wh ere it echoes out the calling script's name in purple at the bottom -- that's what I've been trying to make happen this whole time! THANK YOU SO MUCH!!

1685735885693.png
 
I have no clue what you're doing but %? might be more appropriate than %_?.

I'm trying to write a bat file, ERRORLEVEL.BAT, that solves all my "find out right away when anything breaks ever and let me know" problems for life with the maximum ease-of-use and informativeness.

And I finally got it working after way too many hours.

I'm actually interested in either of those values being >0

I like yours better but I want to check both.

Thanks for the tip, I just put that in! I want the most expansive capture possible, since it may be impossible to prevent internal commands from happening after the last actual program runs.

GOOD CATCH THANK YOU VERY MUCH!!
 
%_? is the exit code of the last INTERNAL command. If you want the exit code of a BTM or VBS (both tested) and probably PY you need %?.
 
And that snippet about variables is simply wrong (where did it come from?).

%_? and %? are not the same.

%_? is for INTERNAL commands

%? is for EXTERNAL things
 
And that snippet about variables is simply wrong (where did it come from?).

%_? and %? are not the same.

%_? is for INTERNAL commands

%? is for EXTERNAL things

Sorry, a typo led me to leave an erroneous comment which I later realized was erroneous and have sine edited to be correct :)
 
%_? is for INTERNAL commands
%? is for EXTERNAL things

Thank you for this, I totally forgot there were two different ones, which is very important foundational knowledge for the reliability of what I'm writing.

Now it's pretty expansive - it uses the higher of either errormessage, thus being more likely to capture more situations.

Hot damn. That was a good tip!
 
As an update, I'm now having problems passing parameters across multilpe bat files with a |

And the problem is absolutey centeredin this alias

And a problem i've been unable to solve

From what I can tell, i have to undo this alias to not break other commands, which breaks my errorlevel cacher

So these workaround are not efficient.

I just spent 45 minutes failing to pass parameters to a bat file because of this alias.
Internally storing the parameters and then passing them just doesn't seem to work.

All kinds of stuff is broken for me now and I can't fix it without removing this alias.

So, I don't think these workaround are actually sufficient.

Just how hard can I beg for an automatic variable?
 
Nobody has ever asked previously for the parent batch file name.


Hi Rexx,

I'm really trying to make my BAT files reliable by adding a generalized no-parameter-error-checker after every call, but alas:

After further testing.... I cannot use the alias solution above to help generate a meaningful error message about what the calling BAT file was. (Of course this can be manually passed, but ease-of-use is my goal because i want to paste this in about 250-500 places)


While the alias solution above meets the needs of simulating a %_callingfile automatic variable, it destroys parameters in some situations, but not others.

I am admittedly at wit's end this morning just trying to pass parameters, something I've been doing since the 1980s.

I've messed around with it for 45-60 minutes.


How hard can I beg for this new automatic variable? Pleeeeeeeeeeeeeeeeeeeease????



Example of the call alias's parameter destruction below. Hil.bat is simply a passthrough "alias bat" for highlight.bat

But with the new call alias, it fails.
Removing the alias, it succeeds.

This drove me crazy this morning.

Also confounding the situation is me having recently changed my parameter character, which brings the total moving parts to a bit higher than what i can simultaneously comprehend

I'm trying to bring my life up to speed and make my workflows more reliable, but change is hard!

1685968462274.png
 
Last edited:
Note that hil.bat using "%1$" instead of "%*" doesn't change the situation, nor does "%1 %2 %3 %4 %5 %6 %7 %8 %9" (the fallback often go back to) ... the parameter stack to transfer through the alias just fine, but not when piped. I think that's what's happening.

Also, just for a glimpse into the madness over here, enjoy the schadenfreude of this screenshot :)

1685969141910.png
 
That must be the problem.
 

Similar threads

Back
Top