5

使用“C:\Program Files (x86)”时,我遇到了一个奇怪的问题,即位于该路径下方某处的程序。我用测试程序重现了这种行为。

    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;
}

该程序计算并返回所有命令行参数(包括用于标识程序的程序路径)。我把它命名为“HelloWorld.exe”,因为我很着急。

对于运行程序的三种可能方式,它给出了两种不同的结果,而我期望得到相同的结果。

当我从自己的目录运行 HelloWorld.exe 时,输出是

1
HelloWorld.exe

该输出是正确且符合预期的。

当我从另一个位置运行位于“P:\Test (x86)”中的 HelloWorld.exe 并使用引用的路径时,输出为

1
P:\Test (x86)\HelloWorld.exe

该输出也是正确和预期的。

但是,当我从另一个位置运行 HelloWorld.exe 并使用带有转义空格和括号的路径时,找到了程序(即路径正确),但输出错误:

2
P:\Test
(x86)\HelloWorld.exe

出于某种原因,逃逸的空间

P:\Test\^ ^(x86^)\HelloWorld.exe

出于某种原因,它变成了一个空格读取操作符,Windows 在将路径作为一个字符串读取以找到程序之后,在创建程序然后引用的数组之前决定它实际上是两个字符串。

此行为在 Windows XP (x86) 和 Windows Server 2008 R2 (x64) 中都会出现。我假设它存在于所有 (NT) 版本的 Windows 中。

4

1 回答 1

5

更新:

哎呀。也许这是 Windows 中的一个错误(或者该术语可能是错误的)。

我刚刚制作了一个快速的小测试程序,它只是简单地调用GetCommandLine()并将其打印到控制台。

我用以下方式调用它:

测试的^雨^在^西班牙^主要是^上^上^平原^^(或^所以^他们^说^)。

这是输出:

测试西班牙的雨主要落在平原上(或者他们这么说)。

所以我猜运行时库根本看不到插入符号,你唯一的选择是告诉你的用户使用引号而不是转义符。


不,这不是 Windows 中的错误。这是您的 C 运行时库中的一个错误(尽管在这种情况下我可能更喜欢术语缺点或缺陷)。

Windows 正在处理转义字符并定位您的可执行文件。但这并不是将命令行分成参数的原因。Windows 不是调用你的main函数(或_tmain在这种情况下)。它只是在 PE 标头中定义的入口点开始您的进程。在这个位置是一些 C 库代码(或对其的动态调用),在其他启动任务中,它调用 kernel32 函数GetCommandLine(),然后将其拆分为空格,尊重引号,但显然不是插入符号转义。

这并不奇怪,真的。我认为大多数人不知道您可以在 Windows 命令行上使用脱字符号转义字符。我当然没有。

如果这对您造成了现实世界的问题,其中有人实际上使用插入符号转义来调用您的程序,您可以告诉他们停止,或者编写自己的命令行解析例程,将输出传递给它GetCommandLine(),和忽略你传递给你的东西main

于 2012-08-24T14:23:23.660 回答