Welcome!

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

SignUp Now!

@ExecStr vs. Call

May
855
0
This is just to verify what I'm 99% I've just discovered that really surprised me in that things don't work the work the way I had always (as in many years) thought (assumed?) that they did. The issue is this: I had always assumed that "Call" ran a batch file in the same process (i.e., same PID) as the caller; whereas a "@Exec...[BatchFileName] ran the batch file in a completely different (new) process (PID), similar to, but much easier to code than, using the "Start" command to run a batch file in that the "output" and return code ("%?") of the started batch file would be much more readily available (and the "/WAIT" option would be implicit), and it would appear that that thought(/assumption) is totally incorrect.

Here's a rough idea of what I was trying to do:

BatchFileA calls BatchFileB calls BatchFileC ExecStr's BatchFileD Calls BatchFileE Calls BatchFileF, and if BatchFileF issues a "Cancel" command, that returns control directly back to BatchFileC, rather than terminating the whole "chain" of batch files starting at the very "top" (i.e., BatchFileA). And, as I'm sure you can guess, I wanted a "Cancel" command in BatchFileF to terminate up to but not including BatchFileC, and that seems to be very clearly not the case. (And while I wasn't really trying to do this, I had an implicit assumption that "Exit" would essentially do the same thing in these circumstances and terminate the (assumed to be separate from the TCC instance running BatchFileA) TCC instance in which it was executed rather than terminating the TCC instance in which BatchFileA was run). And while using a "Start" command is certainly doable, managing the "communications" between the "Started" code and the code "Starting" that code is somewhat non-trivial in that the only way that can happen, it would appear to me, is to have the "Started" code write its output (effectively including a return code) to a temporary file (@Unique) that is "passed" to it by the code that is "starting" the process (chain of batch files) that would be writing its output to that temporary file, and the "caller" would have to do a "Start /Wait" to run the "called" code, and then read the "output" of the "called" code from the temporary file when the "Started" code terminated. So, multiple questions: Am I correct in this "analysis"? And is there any easier way other than the "Start" command to do what I was trying to accomplish? Admittedly, I could do some "experimentation" to check this out: Was my (previous) assumption that "@Exec..." functions did an implicit "SetLocal" and "EndLocal" on the batch function being Exec'd correct, and that you could therefore not do an "EndLocal VariableName" to pass a "variable" back up to the caller because the caller and the callee had separate and distinct "environments"? And the only basic difference between "Run" and "@Exec..." when executing a batch file is that "Run" can not "read" whatever is written to STDOUT by the executed batch file; the executed batch file must return values to the caller by means of an "EndLocal list-of-variables"? I'd prefer to know this, if possible, before moving on to the task of "rearchitecturing" all of existing my code.
 
This is just to verify what I'm 99% I've just discovered that really surprised me in that things don't work the work the way I had always (as in many years) thought (assumed?) that they did. The issue is this: I had always assumed that "Call" ran a batch file in the same process (i.e., same PID) as the caller; whereas a "@Exec...[BatchFileName] ran the batch file in a completely different (new) process (PID), similar to, but much easier to code than, using the "Start" command to run a batch file in that the "output" and return code ("%?") of the started batch file would be much more readily available (and the "/WAIT" option would be implicit), and it would appear that that thought(/assumption) is totally incorrect.

CALL will always run a batch file in the same process. @EXEC and @EXECSTR act like a nested call to the command interpreter, so they will always run a batch file in the same process (and anything else other than an internal command in a new process).

@EXEC / @EXECSTR do not do an implicit SETLOCAL / ENDLOCAL. But you also cannot do a SETLOCAL in one batch file and an ENDLOCAL in another one -- they must be in the same batch file, and TCC will do an automatic ENDLOCAL if you neglect to specify it when the batch file ends.

I don't know what you're referring to by "Run". If you want to read the output written to STDOUT by a batch file, you'll have to use redirection (probably wrapped in a command group).
 
Thank you for you answers, Rex, you pretty much answered all of my questions (and clearly some of my previous assumptions were wrong). But I didn't understand your question about my question about "running" things. Telling you what you very clearly and obviously know (;) ) "@ExecArray" executes a something and returns the data written to STDOUT by that something in an array that can then be "scanned through" (in either direction; or even more significantly, "random(ly) accessed"). I am not aware of a facility for executing something in any other way and capturing its output other than redirecting the output of the something to a (presumably temporary) file which you would then probably use an "@ExecArray[Type ...]" command to put its output into an array if you wanted "random access", and I very often do because I would guess at least 75% of the time I know what lines I am specifically interested in/not interested in "ahead of time" without even "looking" at any of the other lines in the array, and it is not at all unusual for me to access lines in that array in a "random" order which means I don't have to know up front which other lines in the array I may be interested in based upon the contents of other the lines of the array.

And when I say "run", I simply mean "executing" something that is "executable", such as an ".exe" file, a ".bat" file, a ".msi" file, a ".cmd" file, etc. etc. etc. including .btm files, of course. And my basic philosophy (which has generally worked very well up to this time) is that an executable is an executable regardless of which of the above (or other) extensions are involved and what .exe program (if the file being "executed" is not, itself, a .exe file) has to "interpret" the "instructions" in the file, Perl, REXX, ..., and, of course, the TCC batch file interpreter. And I know of only two ways to capture the "output" of an executable: write it to a file via redirection or write it into a variable or an array re. an "@Exec..." function. While I suppose it's completely possible that I am incorrect somewhere in the above, I really kind of doubt it...
 
And I know of only two ways to capture the "output" of an executable: write it to a file via redirection or write it into a variable or an array re. an "@Exec..." function.

There's a third way -- use input redirection or a pipe to send the output of an executable to the STDIN of another executable (or some of the internal commands).

There's several other more obscure ways to do it (named pipes, mailslots, memory buffers, etc.) but they're not commonly needed.
 
Rex, I am aware of (to some degree at least) all of those techniques, and, simply put, none of them apply in these situations. I want to execute an "executable" of some kind in a batch file, and then be able to process the "output" of said "executable" in a "random-access" manner.
 

Similar threads

Back
Top