On this article I will briefly discuss how to get the command
line with which a process was started. The technique I'll describe will allow
you to actually find out the command line for any process, not just the
one your code is running in. It's a fairly common question, so here's the
As it turns out, some process specific data is stored by
NT at address 0x00020498 for any given process. The format of this data goes
something like this:
1. The directory from which the application was loaded.
2. The current directory (represented by a single dot ".").
3. %SystemRoot%\System32. (usually C:\WinNT\System32")
4. %SystemRoot%\System. (usually C:\WinNT\System)
5. Just %SystemRoot%. (usually C:\WinNT)
6. The contents of the PATH environment variable, with one minor adjustment:
before it goes the startup dir of the parent process, but only when that
directory is not included in the PATH already.
Here I have to say that all this was found by experimentation
and fooling around with the debugger. I also thank Slava M. Usov, who was
really the one who figured out that the data format until here was very similar
to what the CreateProcess() documentation state is the directory search
Just after this goes the command line path, followed by the full
command line, which is the part that actually interests us. Finally, the
executable name appears one more time (might, or might not have
the path included), followed by the Window Station and Desktop the process is
running on. In some cases, the window station and desktop might not
appear, if the process is not attached to one.
Worth noting: The full data block is in Unicode (which is
logical), so the sample app is written completely in Unicode. Also, the
technique I used works on NT4 and up. To try the sample app, just compile it,
and run it like this:
where pid is
the process id of the process you wan to get the command line for.
Get the code here, and look it over,
there are some important notes along with the code.
Finally, some advice: As you've probably noticed, this technique
relies on undocumented layouts of the process environment block, which is
subject to change at any time. If you want a really bullet-proof method (at
least for Win32 processes), you can do the folllowing:
Use CreateRemoteThread() to inject some code into the
Call GetCommandLine() from within the injected code.
IPC the results back to your app.
The obvious problem with this technique is that it seems awfully
complicated just to do such a simple thing. The other reason I don't like it is
that is essentially invasive. Felix Kasza has a sample on doing it this way on