The format of the command line returned by GetCommandLine
is “program args
“, but this is only a convention. If you pass NULL
for the lpApplicationName
to the CreateProcess
function, then the CreateProcess
function will treat the first word of the lpCommandLine
as the program name. However, if you pass a value for lpApplicationName
, then that string determines the program that is run, and the string passed as the lpCommandLine
is not used for that purpose.
This means that if somebody runs your program with the following parameters to the CreateProcess
function
lpApplicationName |
= |
"C:\Path\To\Program.exe" |
lpCommandLine |
= |
"slithy toves" |
then when your program calls the GetCommandLine
function, it will get the string "slithy toves"
, which doesn’t give your program much help at all in determining its own name or location.
If your program needs to determine its own name and location, use the GetModuleFileName
function, as I noted some time ago.
What is the point of letting a program specify something different as the first word on the command line from the actual program being run? There isn’t much point to it in Windows, although it is used to greater effect in unix, where you can run a program under various “alias” names, executing one program but lying to it and putting a different name at the start of the command line. Some programs are specially designed to be run this way and alter their behavior depending on the “alias” name they were given. For example, the visual editor runs in screen mode if its name is given as "vi"
but in line mode if its name is given as "ex"
.
Although extremely few Windows programs use this quirk (I am not aware of any myself), the behavior nevertheless is supported, and you need to be aware of it when writing your own program, even if you don’t intend to use it.
For example, if you forget to repeat the program name on the command line and create the process like this
lpApplicationName |
= |
"C:\Path\To\Program.exe" |
lpCommandLine |
= |
"arg1 arg2" |
then when that program runs, you will most likely see it ignore the arg1
because it thinks that arg1
is just the program name. If that program is a console program that uses the C runtime startup code, then it will receive its parameters as
argv[0] |
= |
"arg1" |
argv[1] |
= |
"arg2" |
As I noted earlier, most console programs merely ignore their argv[0]
since that slot is just the program name. (In this case, it’s the alias program name, but the program being run doesn’t know that.)
Similarly, if the program is a Windows program that uses the C runtime startup code, then the C runtime startup code will merely skip over the first word on the command line, passing "arg2"
to the WinMain
function as its lpCmdLine
.
What was the point of all this discussion? Two things. First, that if you are launching other programs and passing an explicit lpApplicationName
, then it behooves you to format the command line in a compatible manner. Otherwise, the results may not be what you expect. Second, that you as a program should not use the first token on the command line to control any security decisions since the value is controlled by the launcher and need not have any connection to reality.
0 comments