Working with "C:\Program Files (x86)" I ran into a strange issue with a program located somewhere below that path. I reproduced the behaviour with a test program.
int _tmain(int argc, _TCHAR* argv[])
{
wprintf(L"%d\n", argc);
for (int i = 0; i < argc; i++) {
wprintf(L"%s\n", argv[i]);
}
return 0;
}
The program counts and returns all command line arguments (including the path to program used to identify the program). I named it "HelloWorld.exe" because I was in a hurry.
For three possible ways to run the program it gives two different results, whereas I was expecting the same result.
When I run HelloWorld.exe from its own directory, the output is
1
HelloWorld.exe
That output is correct and expected.
When I run HelloWorld.exe, which is located in "P:\Test (x86)", from another location and use the quoted path, the output is
1
P:\Test (x86)\HelloWorld.exe
That output is also correct and expected.
However, when I run HelloWorld.exe from another location and use a path with escaped spaces and brackets, the program is found (i.e. the path is correct), but the output is wrong:
2
P:\Test
(x86)\HelloWorld.exe
For some reason the escaped space in
P:\Test\^ ^(x86^)\HelloWorld.exe
becomes a space-read-as-operator for some reason and Windows, after reading the path as one string to find the program, decides that it is really two strings after all before creating that array the program then refers to.
This behaviour occurs in both Windows XP (x86) and Windows Server 2008 R2 (x64). I assume it is present in all (NT) versions of Windows.
Open your Windows Security settings. Select Virus & threat protection > Scan options. Select Windows Defender Offline scan, and then select Scan now.
We have received reports that some types of SSL and TLS connections might have handshake failures. Files or shortcuts might not copy or copy as zero-byte files when using Group Policy Preferences on client devices. Windows 11 devices with the affected Intel SST driver might receive an error with a blue screen.
Select Start > Settings > Update & Security > Troubleshoot, or select the Find troubleshooters shortcut at the end of this topic. Select the type of troubleshooting you want to do, then select Run the troubleshooter. Allow the troubleshooter to run and then answer any questions on the screen.
After installing updates released June 14, 2022, you might have issues using Wi-Fi hotspot on Windows device. You might receive Error code: 0xC002001B when attempting to install apps from the Microsoft Store. You might have intermittent issues, apps might close unexpectedly, or you might receive an error.
Update:
Oops. Maybe it is a bug (or perhaps the term is misfeature) in Windows.
I just made a quick little test program that simply calls GetCommandLine()
and prints that out to the console.
I called it with:
test The^ rain^ in^ Spain^ falls^ mainly^ on^ the^ plain^ ^(or^ so^ they^ say^).
And this is the output:
test The rain in Spain falls mainly on the plain (or so they say).
So I guess the runtime library never sees the carets at all, and your only option is to tell your users to use quotes instead of escapes.
No, it's not a bug in Windows. It's a bug (although I might prefer the term shortcoming or deficiency in this case) in your C runtime library.
Windows is processing the escape characters and locating your executable. But it's not what separates the command line into arguments. Windows is not what calls your main
function (or _tmain
in this case). It simply starts your process at the entry point defined within the PE header. At this location is some C library code (or a dynamic call into it) that, among other startup tasks, calls the kernel32 function GetCommandLine()
, then splits that on spaces, honoring quotes, but not, apparently, caret escapes.
It's not very surprising, really. I don't think most people know that you can escape characters with carets on the Windows command line. I certainly didn't.
If this is causing a real-world issue for you, where somebody is actually using caret escapes to invoke your program, you can either tell them to stop, or write your own command-line parsing routine, passing to it the output of GetCommandLine()
, and ignore what you get passed to you in main
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With