tags:

views:

41

answers:

3

Is there a way for a batch file (in this case, running on Windows XP) to determine whether it was launched from a command line (i.e. inside a console window) or launched via the shell (e.g. by double-clicking)?

I have a script which I'd like to have pause at certain points when run via the shell, but not when run at a command line. I've seen a similar question on SO, but am unable to use the same solution for two reasons: first, whether or not it pauses needs to be dependent on multiple factors, only one of which is whether it was double-clicked. Second, I'll be distributing this script to others on my team and I can't realistically ask all of them to make registry changes which will affect all scripts.

Is this possible?

A: 

I don't know the answer, but thing that would be simple to try is adding the following to the top of your batch file: set > variables.txt and compare the result of invoking from the command line to running via the shell, to see if there are any environment variables that are set differently.

the_mandrill
No such luck, their environments (or at least their `SET` outputs) are identical.
Ben Blank
A: 

One approach might be to create an autoexec.nt file in the root of c:\ that looks something like:

@set nested=%nested%Z

In your batch file, check if %nested% is "Z" - if it is "Z" then you've been double-clicked, so pause. If it's not "Z" - its going to be "ZZ" or "ZZZ" etc as CMD inherits the environment block of the parent process.

-Oisin

x0n
Interesting idea, but it doesn't seem to work. `AUTOEXEC.NT` seems to be ignored completely, `AUTOEXEC.BAT` gets executed only once (at system startup), and the AutoRun registry key gets executed once per `CMD.EXE` session regardless of how it was launched.
Ben Blank
Batch files don't get started in a new `cmd` process. So if I just fire up a `cmd` instance and start the batch file from there, `nested` will be `Z`. Otherwise a nice idea for detecting nested shells, but not suitable for batch files.
Joey
Another note: `autoexec.nt` never resided in the root directory of the drive but instead in `%systemroot%\system32`. As far as I know it only affects `command.com`, not `cmd`, though.
Joey
oh well. sometimes it's just worth posting your thoughts in the hope that it might trigger someone else's brainwave.
x0n
+3  A: 

Found one :-) – After desperately thinking of what cmd might do when run interactively but not when launching a batch file directly ... I finally found one.

The pseudo-variable %cmdcmdline contains the command line that was used to launch cmd. In case cmd was started normally this contains something akin to the following:

"C:\Windows\System32\cmd.exe"

However, when launching a batch file it looks like this:

cmd /c ""C:\Users\Me\test.cmd" "

Small demo:

@echo off
for %%x in (%cmdcmdline%) do if %%~x==/c set DOUBLECLICKED=1
if defined DOUBLECLICKED pause

This way of checking might not be the most robust, though, but /c should only be present as an argument if a batch file was launched directly.

Works on my machine

Tested here on Windows 7 x64. It may or may not work, break, do something weird, eat children (might be a good thing) or bite you in the nose.

Joey
Bah. I was just playing around with something similar, but was trying to determine if `%CMDCMDLINE%` contained `%0`. Checking for `/c` is *so* much easier, though, and I can't think of any edge cases where my approach would have worked but this wouldn't. Thanks!
Ben Blank
Joey
@Joey — I was actually using substring tricks rather than `FOR`, but batch is not well-suited for string manipulation. Your `/c` trick is much simpler and easier and should work unless the user is doing something *really* weird.
Ben Blank
I was also thinking about checking tasklist.exe output (it has some nice comparison operators) - the window title in particular. i thought that it might contain some hints, like the path of the batch file when double clicked, but alas, no.
x0n