我有以下代码,用于从程序中运行批处理脚本:
#include <string>
#include <tchar.h>
#include <iostream>
int main()
{
std::wstring command = _T("\"C:\\cygwin64\\home\\ravik\\path with space\\sample.bat\"");
std::wstring arg1 = _T("C:\\cygwin64\\home\\ravik\\another_space\\test");
std::wstring arg2 = _T("\"C:\\cygwin64\\home\\ravik\\another space\\test\"");
std::wstring fullCommand1 = command + _T(" ") + arg1;
_wsystem(fullCommand1.c_str());
std::wstring fullCommand2 = command + _T(" ") + arg2;
_wsystem(fullCommand2.c_str());
std::cin.get();
return 0;
}
在 fullCommand1
和 fullCommand2
中,我使用相同的命令(即 sample.bat
),但传递不同的命令行参数到所述命令(arg1
vs arg2
)。但是,虽然在使用 fullCommand1
时 _wsystem
命令按预期工作,但当我使用 fullCommand2
时,我收到错误
'C:\cygwin64\home\ravik\path' is not recognized as an internal or external command, operable program or batch file.
似乎不知何故,第二次调用_wsystem
时,围绕我的路径的空格
的“
消失了。原因是什么这个?
最佳答案
为什么会发生这种情况?
Microsoft C 运行时的 system() 和 _wsystem() 实现存在设计缺陷,在这种情况下会导致您陷入困境。
您尝试运行的命令如下所示:
"c:\path with spaces\my.bat" "argument with spaces"
C 运行时采用最简单的方法,将其转换为
cmd /c "c:\path with spaces\my.bat" "argument with spaces"
不幸的是,cmd.exe
有 rather arcane rules当请求的命令中的第一个字符是引号时,在这种情况下最终将命令解释为
c:\path with spaces\my.bat" "argument with spaces
由于显而易见的原因,这不起作用。
(我说这是一个设计缺陷,因为如果运行时使用/S 开关并在命令周围添加引号,那么它在每种情况下都可以完美工作。出于向后兼容性的原因,这可能无法修复。或者也许它只是不是运行时开发团队的优先事项。)
无论什么原因,结果都是你必须自己解决问题。
在这种特殊情况下我该如何解决它?
在这种特殊情况下,最简单的解决方案是使用如下命令:
""c:\path with spaces\my.bat" "argument with spaces""
运行时会将其变成
cmd /c ""c:\path with spaces\my.bat" "argument with spaces""
将根据需要进行解释,因为有两个以上的引号。使用此方法时您只需要小心一点,因为有时只需要额外的引号可能会导致困惑。
(即使不需要额外的引号,几乎总是安全的,但是存在潜在的歧义 - 如果可执行文件的路径与命令行参数相结合碰巧形成了到不同可执行文件的有效路径。请参阅上面链接的答案的附录以获取示例,尽管这是一个相当人为的示例!)
一般情况下如何修复它?
最通用的解决方案是将命令字符串指定为
cmd /s /c ""c:\path with spaces\my.bat" "argument with spaces""
运行时会将其变成
cmd /c cmd /s /c ""c:\path with spaces\my.bat" "argument with spaces""
将运行
cmd /s /c ""c:\path with spaces\my.bat" "argument with spaces""
这将被解释为
"c:\path with spaces\my.bat" "argument with spaces"
根据需要;由于/S 标志,即使您运行的命令没有任何引号,此变体也将始终按预期工作。
这种方法确实意味着有两个 cmd.exe
实例正在启动,一个在另一个内部;如果这种轻微的开销是 Not Acceptable ,您始终可以选择直接使用 CreateProcess 而不是调用 system()。
(最好自己调用 CreateProcess 的另一种情况是,如果您需要在命令行上使用插入符号或其他特殊字符。)
关于c++ - 在 _wsystem 中转义引号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44637891/