Is it possible to obtain the _raw_/_unprocessed_ command line? - winapi

The windows API provides GetCommandLine() which returns the cooked command line used to start a process.
For instance, if a console application is started with the command:
MyProg.exe > OutputHere
The command line seen by MyProg.exe will not include the portion
> OutputHere
I'd like to somehow get the command line exactly as it was. Is this possible ? and if yes, how ?
Suggestions in C and/or plain (no objects) Delphi greatly appreciated. Creative solutions welcome (hopefully, not requiring ring 0 code.)
Thank you very much for your help.
NOTE: I can tell if the input/output, etc has been redirected but, that is not what I'm looking for. I need the original/uncooked command line.

The redirection or piping of stdin, stdout and stderr is handled the command interpreter, typically cmd.exe. The interpreter parses the command and creates the necessary files and pipes, and then creates the one or more processes needed to implement your command.
The processes that are created have no knowledge of the original command, they only get that part of the command that is not related to piping and redirection.
So what you are trying to do is not possible, at least within your process. The only thing that knows the original command is the command interpreter.

Whether or not you can retrieve the full command line including the pipe commands depends on whether your start the program in a command window or for example using the "Run" command from the Start menu. If you use the "Run" command from the Start menu GetCommandLine actually retrieves the full command line including the redirection commands, but redirection does not work as it seems to be a feature of CMD.EXE.
As others have pointed out, what are you trying to achieve here / why do you need to capture the redirection commands?

Related

Why can't I redirect stdout/err of a program run by a batch file, called by another batch?

If I have this batch:
ScriptA.bat
someprog.exe
And this one:
ScriptB.bat
CALL ScriptA.bat
And I execute a command like:
ScriptB.bat > test.log
The output from someprog.exe is not logged. It flows through to the console. How can I avoid having to explicitly pipe the output of someprog.exe to a file, and instead just capture that from a higher level?
(Note I ultimately want to do this with a great many scripts launching assorted exes from inside those nesting, and I can't edit them all to redirect the output of each and every sub process they invoke).
I found the answer to this on another SO thread:
https://stackoverflow.com/a/11955380/3220983
As you'll see if reading the comments under the question, the problem I was encountering was that the messages I couldn't capture were not being piped to stdout or stderr at all! They were going straight to the console via something akin to a CON redirect from inside the specific executable I was trying to use.
The link I posted shows how to launch a PowerShell script from a batch script, which captures the entire console window contents, inclusive of CON output!

Redirecting cmd stdout and stderr back to parent

If I create a process from a cmd prompt using the start command (opening a new cmd) is it possible to redirect the stdout and stderr from that process back to the calling cmd?
If you want the output of the STARTed process to appear in the parent command console, then simply use the START /B option.
If you want to process the output of your command, then you should use FOR /F ... in ('someCommand') DO ... instead.
OK. I have yet to find a straightforward answer to this question. I didn't want to bog down my question with what I thought unnecessary detail but seeing as I'm being criticized for the lack of this I'll expand a bit here.
I want to automate the updating of FWs on our production line, so I've a python app that gets the FWs from ftp and then uses the processors flash tool via python subprocess command to upload it to the board's flash. OK for all but one of the tools.
The one tool seems to have a problem when it's not running in its own terminal, so I provide a start to the subprocess command string which allows it to run OK in its own terminal. However, I need the output from this other terminal for logging reasons.
A possible solution was to log stdout and stderr to file using >> or wintee and then poll this file via a thread in my original app (perhaps a rather convoluted solution to the question). However the tool also has a separate problem where it doesn't like any std redirection, so this doesn't work for me.

Run a simple shell command

What is the best WinAPI function to use when you only want to run a simple shell command like hg > test.txt?
To simply run a file, then ShellExecute() and CreateProcess() are the best options.
As you want to redirect output to a file/run a shell command, it complicates things...
Output redirection is a feature of the command prompt, and as such, the command you want to run needs to be passed to cmd.exe (on NT/XP+) passing /c and your command as the parameters (either ShellExecute or CreateProcess will do).
cmd /c "ipconfig >c:\debug\blah.txt"
The best way however is to use CreateProcess() and create your own pipes to talk to the stdin and stdout of the program (This is all cmd does internally)
You could use ShellExecute(), but why not try system() first? I am not so sure that ShellExecute() can actually do piping or redirection. There is also CreateProcess(), but that requires a bit more work. CreateProcess() gives you the best control, though.
There are two ways of issuing commands: the Windows Shell way, and the command line way.
Windows Shell issues commands by executing verbs on files. Verbs are associated with file types in the registry. Examples of common verbs are Open and Print. The WinAPI to use for this is ShellExecute. Windows Shell does not help you pipe the output of a process to a file. You can do it using CreateProcess, but it is a little bit involved.
The command line way is to use the system function.

Redirect CMD.exe output to a pipe

Can I use CreateProcess (or ShellExecute, or any other means of invoking cmd.exe to run a batch script) and have all output redirected to a pipe owned by my process? How do I give the child cmd.exe process a handle to one of the pipe endpoints? Is it even possible to use a pipe in this way?
(Googling for variations on the terms "cmd.exe" and "pipes" is nothing but redirecting output to another program using the |(pipe) character)
Here's how you would do it with .NET: http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.redirectstandardoutput.aspx
And for C/C++: http://msdn.microsoft.com/en-us/library/ms682499(v=VS.85).aspx
Probably this will help... it is in VB.NET but it shouldn't be hard to change it to C#...
http://blogs.msdn.com/b/rahulso/archive/2006/04/01/run-a-command-from-the-command-prompt-and-get-its-output-in-a-windows-application.aspx

Is there any way to redirect stderr output from a command run with “start” in the Windows command line?

I have a program that I want to automate runs for, since it takes awhile to complete. For some reason it outputs everything to stderr instead of stdout, and I'd like to check on its progress, so I find myself needing to redirect stderr output within a start command.
I tried this:
start "My_Program" "C:\Users\Me\my_program.exe" --some --presets --for --my_program.exe --output "C:\Users\Me\output_file_for_my_program" "C:\Users\Me\input_file_for_my_program" 2>"C:\Users\Me\my_program_output.log"
But it turns out that the redirect is being picked up by start, so that I get a 0-byte file with the result of "start" - namely, nothing. Is there any way to make the output redirection attach in some way to the output of my_program?
I've experimented with escaping, and neither "^2>" nor "2^>" seem to work.
If "Workaround Oriented Programmming" is acceptable (it probably is, you are programming Windows Batch lol), you could put the problematic code line in another .BAT file, without any "start" and then "start" this other BAT.

Resources