And*_* Li 5 c windows command-line cmd command-line-arguments
在我看来,Windowscmd.exe解析参数字符串的方式与 C 编译的 exe 的正常方式不同。
为了说明,cmd /C "echo ok"正确打印“ok”。但是,cmd "/C" "echo ok"结果是
'"echo ok' is not recognized as an internal or external command,
operable program or batch file.
Run Code Online (Sandbox Code Playgroud)
为了进行比较,这里有一个 C 程序“CommandArguments.c”,它逐行打印参数:
int main(int argc, char *argv[])
{
int i;
for (i = 0; i < argc; ++i) {
printf("%s\n", argv[i]);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我运行CommandArguments.exe "/C" "echo ok",它会正确打印
CommandArguments.exe
/C
echo ok
Run Code Online (Sandbox Code Playgroud)
我问这个是因为我正在实现一个 API 来包装CreateProcess. 在传递给CreateProcess. 它适用于大多数事情,但不适cmd用于上述问题。
所以,我想知道为什么cmd行为不同?它的参数解析规则是什么?是否有其他程序也以不同的方式解析参数?
任何应用程序都可以以其认为合适的任何方式解析命令行。大多数应用程序使用 C 运行时库解析器,但没有要求这样做。
理想情况下,您的 API 应要求调用者为命令行提供单个字符串而不是参数数组,因为这是启动 Windows 进程的正确语法。
如果这不可行,您至少应该为调用者提供一个选项来执行此操作,以防目标应用程序需要特殊处理。
至于命令处理器,其解析行为记录在内置帮助(cmd /?)中:
如果指定了 /C 或 /K,则将开关后的命令行剩余部分作为命令行处理,其中以下逻辑用于处理引号 (") 字符:
如果满足以下所有条件,则保留命令行上的引号字符:
- 无 /S 开关
- 正好两个引号字符
- 两个引号字符之间没有特殊字符,其中特殊字符是以下之一: &<>()@^|
- 两个引号字符之间有一个或多个空白字符
- 两个引号字符之间的字符串是可执行文件的名称。
否则,旧的行为是查看第一个字符是否是引号字符,如果是,则剥离前导字符并删除命令行上的最后一个引号字符,保留最后一个引号字符之后的任何文本。
这有点混乱,但您可以通过提供 /S 开关来简化它。如果您要运行的命令[foo]只是使用
cmd /s /c "[foo]"
Run Code Online (Sandbox Code Playgroud)