Author
Topic: Suggestion: Use Comspec (Read 27008 times)

Instead of statically calling cmd wherever it is needed, please use the ComSpec environment variable to determine what command processor to use (It's been around since ms-dos, and still exists).The comspec variable always points to the full path of the command processor to use and doesn't contain parameters.

It wouldn't change anything for standard users, but it would for those that want to use an alternate command processor by default.

In my case I prefer to use Take command by jpsoft which is compatible with the normal command processor, but oh so powerful in comparison.

This never occurred to me.Actually D+DR just tells the OS to launch the program, so the OS takes care of it, but perhaps i could have an option to manually specify a replacement command processor.

If you specify the command processor exe on the D+DR commandline before the program to execute, does it work?

Or do you have any alternative explanation for how to launch another exe programmatically using an alternative command processor. Remember that D+DR needs to capture the output of the processor in some cases which involves remapping the i/o, so i'm curious to know if this will still work ok.

This never occurred to me.Actually D+DR just tells the OS to launch the program, so the OS takes care of it, but perhaps i could have an option to manually specify a replacement command processor.

If you specify the command processor exe on the D+DR commandline before the program to execute, does it work?

Or do you have any alternative explanation for how to launch another exe programmatically using an alternative command processor. Remember that D+DR needs to capture the output of the processor in some cases which involves remapping the i/o, so i'm curious to know if this will still work ok.

Yes, D+DR grabs the output as it should when specified on the D+DR commandline.

I'm talking about every time you would normally explicitly call the command processor (as you or a library apparently do with .bat for instance),not .exe etc extensions.

I have .cmd,.bat and .btm extensions assigned to run with "c:\program files\jpsoft\tcmd9\tcc.exe".The comspec variable is also assigned that path, so no matter what, everything running a batchfile one way or anotherwould run with TCC instead of XP's command processor.

I did some testing by creating a small batch file (test.bat) containing only VERthen dropped a file in D&DR, and ran it. It shows XP's command processor:

Microsoft Windows XP [Version 5.1.2600]

with TCC it would've shown:TCC 9,02.151 Windows XP [Version 5,1,2600]

which it doesn't, ergo D&DR seems to call it directly, ignoring extensions and comspec.

Regarding captures etc.. You should be able to do exactly the same as you already do.

Below I use %comspec% when referring to where you'd use the returned string from SysUtils.GetEnvironmentVariable('ComSpec').

Note that you could already do that manually by putting the full line in the commandline, this would simply be a way to let you specify things differently for general use and then skip having to put the info on the commandline.

But just to clarify i'm understanding things.. if you manually change your commandline item to start with "c:\program files\jpsoft\tcmd9\tcc.exe" then does it do what you want? OR are you saying that this issue only comes up when D+DR is auto-creating .bat files and launching them (which happens when D+DR sees a commandline that doesnt start with a .exe).

myarmor: perhaps you haven't fixed all assignments for .bat/.cmd properly? Try using regmon and see what .bat related entries are looked at when you launch a file with D+DR, perhaps it's related to some of the more obscure stuff like the DropHandler GUID entry... ShellExecute() works in mysterious ways

But just to clarify i'm understanding things.. if you manually change your commandline item to start with "c:\program files\jpsoft\tcmd9\tcc.exe" then does it do what you want? OR are you saying that this issue only comes up when D+DR is auto-creating .bat files and launching them (which happens when D+DR sees a commandline that doesnt start with a .exe).

The above seems like a too complicated way to do things..Yes, cmd.exe is ran when creating temporary batch files too..

This is what happens when running a .bat file:-- Log from Outpost Firewall --23:48:20 Command line: cmd /c "D:\tmp\test.bat"23:48:20 Process CMD.EXE started by draganddroprobot.exe-----------------------------

The "cmd" part of the line above is what I'd like to have changed with the content of the comspec environment variable.The issue is caused by anything starting "cmd" instead of the designated command processor.

The point is, instead of executing cmd /c "D:\tmp\test.bat" in the example above you would execute "%comspec%" /c "D:\tmp\test.bat".Comspec in the preceding sentence is still the expanded contents of that variable.

- Take command understands batchfiles perfectly, but cmd doesn't understand the tcc extensions to the language. you can detect inside a batchfile if it runs under the normal command processor or tcc.- Using the .btm extension would be option, but would result in D+DR first executing cmd, then tcc, for every single file.- Starting all commandlines with c:\program files\jpsoft\tcmd9\tcc.exe /c might also work, but makes it less flexibleto change (such as tcc changing path, or the configuration and batchfile is delivered to someone without Take command) than justthe straight forward d:\tmp\test.bat .

Another way to support this, if you want to do it the hard way, is to support this type of command typed into the D+DR commandline:%VARIABLENAME% parameters or, taken a bit longer%SYSTEMROOT%\notepad.exe "%HOMEDRIVE%\%HOMEPATH%\test.txt"

It might even be more powerful.D+DR would then simply expand the variable(s) provided before interpreting it, then execute.

This way it would still remain flexible, in which you can write %COMSPEC% /c d:\tmp\test.bat, essensially doing the same as I wish for.

The reason that there is a bit of confusion and probably what f0dder is getting at, is the fact that i dont ever call cmd.exe explicitly.

I actually dont use shellexecute either, i usee CreateProcess because it allows me to pipe the output and capture it to be displayed in the program.

So the point is that the OS is the one deciding to launch cmd.exe to execute the .bat files. Which is i think why f0dder was suggesting that maybe there are other places where you should configure the OS to tell windows to always launch .bat files with tcc.exe.

I could however try to either check the environment and try to launch bat files with replacement COMSPEC or allow an option of how .bat files should be launched explicitly rather than relying on OS to decide which program to use.

Question: Would you ONLY use %COMSPEC% for launching .bat files? or would you use it for ALL shelling of any executable?

The reason that there is a bit of confusion and probably what f0dder is getting at, is the fact that i dont ever call cmd.exe explicitly.

I actually dont use shellexecute either, i usee CreateProcess because it allows me to pipe the output and capture it to be displayed in the program.

So the point is that the OS is the one deciding to launch cmd.exe to execute the .bat files. Which is i think why f0dder was suggesting that maybe there are other places where you should configure the OS to tell windows to always launch .bat files with tcc.exe.

I could however try to either check the environment and try to launch bat files with replacement COMSPEC or allow an option of how .bat files should be launched explicitly rather than relying on OS to decide which program to use.

Question: Would you ONLY use %COMSPEC% for launching .bat files? or would you use it for ALL shelling of any executable?

Just to reiterate in case there is still some confusion. it's not a matter of me using %COMSPEC% in place of cmd. because i never use "cmd". The OS chooses to use cmd and the OS invokes it when i call CreateProcess.

So the solution cannot be to use %comspec% in pace of cmd in my code. The solution could be to modify the commandline given to CreateProcess and to manually override the OS choice of command processor by explicitly passing something like CreateProcess("%COMSPEC% NORMAL_COMMANDLINE_HERE") instead of the normal CreateProcess("NORMAL_COMMANDLINE_HERE"). If that works without issue then it's a reasonable solution. I just have to see if that works ok and doesn't break io redirection piping.

I've just done some testing, and it seems that CreateProcess does not respect %ComSpec%. I started a shell, set ComSpec to something silly (zoomin.exe, it has a GUI so it definitely shows up if used) - if I then launch a .bat file (with the "start" command, just typing x.bat doesn't use the (new) ComSpec but the existing cmd.exe instance), sure enough, zoomin starts up.

I then made a little test app that MessageBox()'es it's commandline as well as %ComSpec%, then launched x.bat. Sure enough, %ComSpec% was inherited correctly, but still cmd.exe was launched - so CreateProcess definitely doesn't use it (haven't changed my .bat registry association, so dunno if it was looked up there).

ShellExecute doesn't use %ComSpec% either. Also, I made the batch file print %ComSpec%, and both with CreateProcess and ShellExecute, c:\usr\bin\zoomin.exe was printed, as expected.

So really, this is no fault of mouser's - pretty annoying anyway, as it sounds like .cmd and .bat need special manual handling in order to use %ComSpec%...

EDIT: mouser, you should only do this %ComSpec% thing explicitly for batch files, I doubt console apps launched through a command interpreter will pipe correctly - or at least that there could be issues with it.

right ok, well i'm quite happy to check for the launching of .bat files and use %comspec% when launching them.. the only real question is whether i should just do that always, or do i need an option to let the user say they do NOT want %comspec% being used, and would prefer default of cmd.exe.

second question, assuming i want to just let the OS do it's default when an alternate command shell isn't specified, can i check %comspec% and tell if a replacement shell has been configured. i.e. if i see cmd.exe file in %comspec% shall i just assume its default and let CreateProcess handle the .bat file normally.

third and final question -- is there any value in letting the user manually specify the command shell to use when launching .bat files instead of checking %comspec%. this would be useful for people who want to use an alternate shell not configured through %comspec%

Quoted from the Win32 SDK documentation, CreateProcess:To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the name of the batch file.

It is the cmd.exe part in the text above that is changed to the contents of the comspec environment variable.

// This simply expands the comspec environment variable, then tries to execute a batch file using the expanded contents// as the command processor.// Note, this tidbit looks like h..., has no errorchecking, no redirection, and probably has lots of issues, // but its just a demonstration.

right ok, well i'm quite happy to check for the launching of .bat files and use %comspec% when launching them.. the only real question is whether i should just do that always, or do i need an option to let the user say they do NOT want %comspec% being used, and would prefer default of cmd.exe.

To run a batch file, you must start the command interpreter; set lpApplicationName to cmd.exe and set lpCommandLine to the name of the batch file.

ok well that explains some of our crosstalk.. you probably wont be surprised to hear that i do not do that. i just set applicationname to the batch file name, and the OS is figuring out to launch cmd.exe.

i'll try to get this comspec support in next version, once we decide the answers to my previous questions.

Btw, if you want to check out what I'm talking about, there's a free (limited featureset, still more advanced thanthe default command processor) named TCC/LE, a trial of Take Command, and a trial of Take Command LE at jpsoft.com

--- Mods: I'm not trying to advertise their product, but I thought you might like to look at it and see why I want it to be usedinstead of the normal command processor.

If you consider THIS post to be an advertisement, then please remove it if you want to.

on this forum we welcome people expressing opinions about software they like (the only time you will find people complaining about spam/adverts is when someone signs up for the sole purpose of advertising their software).

I generally set lpApplicationName=0, and construct a fully-qualified pathname (including quotes if necessary (ie., paths including spaces)) for lpCommandLine - this seems to give the most consistant results.

I dunno if the "To run a batch file, you must start the command interpreter" info from MSDN has ever been necessary, or if it's perhaps just a relic from the win3.x days... guess it might be worth firing up a win9x vmware image (and install + test a NT4 image) and see if they work with appname=0 and specifying just the batch file in cmdline.

Getting systemroot and appending cmd.exe definitely breaks Win9x compatibility - there really shouldn't be any systems with %ComSpec% set, and if you want to be really paranoid, don't hardcode anything but check the registry association for .bat (but that's almost at the point of being silly, imho).

second question, assuming i want to just let the OS do it's default when an alternate command shell isn't specified, can i check %comspec% and tell if a replacement shell has been configured. i.e. if i see cmd.exe file in %comspec% shall i just assume its default and let CreateProcess handle the .bat file normally.

-mouser

Good question, really - see, if you simply start cmd.exe with a batch file as argument, you just get a new cmd.exe instance, and no executing batch file. You need to specify /C (run-and-terminate) or /K (run-and-remain) to cmd.exe before the batch file path. This is probably why CreateProcess has special magic for handling batch files in the first place!

Probably the best idea is to drop %ComSpec% entirely (magic'ing it for cmd.exe and command.com sounds like a recipe for disaster), and look up the registry... HKEY_CLASSES_ROOT\{.bat,.cmd} , follow the default value and check the shell\open\command of that key, doing proper expansion of it's default value.

OK, that sounds like too much bother as well, and a lot of opportunities for failing.

third and final question -- is there any value in letting the user manually specify the command shell to use when launching .bat files instead of checking %comspec%. this would be useful for people who want to use an alternate shell not configured through %comspec%

-mouser

Probably the most failsafe method of doing it, and definitely the easiest.

EDIT: I just checked the (32-bit) version of kernel32.dll from my XP64 system, and indeed CreateProcess has hardcoded checks for .bat and .cmd, and hardcodes "cmd /c".

third and final question -- is there any value in letting the user manually specify the command shell to use when launching .bat files instead of checking %comspec%. this would be useful for people who want to use an alternate shell not configured through %comspec%

-mouser

Probably the most failsafe method of doing it, and definitely the easiest.

EDIT: I just checked the (32-bit) version of kernel32.dll from my XP64 system, and indeed CreateProcess has hardcoded checks for .bat and .cmd, and hardcodes "cmd /c".

myarmor: smartest thing would be adding some specific rules for .bat/.cmd and let you specify the app+commandline to use. This could probably be written as some fancy regex thing that could be used for other things as well...

And yeah, this did turn out somewhat convoluted, from what could have been a relatively simple issue - turned out the underlying mechanics are "somewhat fuzzy" though

myarmor: smartest thing would be adding some specific rules for .bat/.cmd and let you specify the app+commandline to use. This could probably be written as some fancy regex thing that could be used for other things as well...

And yeah, this did turn out somewhat convoluted, from what could have been a relatively simple issue - turned out the underlying mechanics are "somewhat fuzzy" though

Yes, it might just work.However, you could turn this into a generally useful thing, as those environment variables could be somewhat useful to access on the D+DR commandline somehow..

I suggested this as an alternative earlier on in this thread as this opens up the comspec for those that wants it, but it also opens up every single environment variable globally defined, such as homedrive,homedir,systemroot, or whatever..

This functionality could make it possible to use the exact same .Ddr for different users, making it possible to unrar files into subfolders of the current users Download folder for instance.And you could send the same file to a friend and he could use it without changes (at least as long as the same language is used).

Regarding the initial comspec implementation itself, I've implemented the suggested behaviour a couple of times myself for some custom utilities without any issues..Usually it's more or less straight forward except detecting .bat and .cmd files, then executing it with the contents of the comspec variable, and prepending "/c " before the commandline itself.

Yes, accessing environment variables from D+DR could be useful enough - I just wonder whether all (or "all the important", anyway) shells interpret "/c" the same way? Also, what if you have your %ComSpec% set to an "alien" shell that doesn't support the .bat file syntax? (ie., bash)? There's lots of issues to consider

By the way, it seems like ShellExecutedoes honor the batfile/cmdfile registry entries, but don't care about %ComSpect% at all. But with ShellExecute, you don't get to redirect stdin/stdout...

Yes, accessing environment variables from D+DR could be useful enough - I just wonder whether all (or "all the important", anyway) shells interpret "/c" the same way? Also, what if you have your %ComSpec% set to an "alien" shell that doesn't support the .bat file syntax? (ie., bash)? There's lots of issues to consider

By the way, it seems like ShellExecutedoes honor the batfile/cmdfile registry entries, but don't care about %ComSpect% at all. But with ShellExecute, you don't get to redirect stdin/stdout...