CreateProcess和命令行参数

背景信息: Windows 7,Visual C ++ 2010 Express

问题: CreateProcess()保持返回“无效的命令行参数

说明:我正在编写一段使用Windows API的CreateProcess调用外部程序的代码。 到目前为止,我已经得到了一个外部程序的调用:

if( !CreateProcess( "C:\\Temp\\convert.exe", t_str, // Arguments ... } //where t_str is " C:\\img1.jpeg C:\\img1.pgm" (ImageMagick if you're wondering). 

即使数据量很大,我也可以将所有内容都推送到Windowsstring和指针中。 所以我复制了所有的CreateProcess()调用另一个外部程序的调用:

  if( !CreateProcess( "C:\\Temp\\sift.exe", t_str2, // Arguments ... } //where t_str2 is ` < C:\\img1.pgm > C:\\img1.key` 

基本上,非常相似的东西,但所有的variables名称更改(因为我有这两个调用运行串行)。 这就是问题所在。 这不会运行,而是打印出“无效的命令行参数:<C:\ img1.pgm”。 当然,这个命令在命令提示符下工作正常,但在我的代码中没有。

我把t_str2转换成了一些不那么复杂的东西(因为我知道sift.exe是如何工作的),并得到了相同的结果。 同样的事情发生时,我只是运行筛选,而不是转换。

问题:什么可能导致这个问题? 我能做些什么来进一步debugging这个问题? 任何关于我正在使用的方法的替代方法的build议? 任何帮助表示赞赏。 我可以提供进一步的代码,但是这是非常简单的,并没有太多的错误。

您不能直接使用带有CreateProcess()命令行重定向操作符。 你必须产生一个cmd.exe的实例,并将运算符传递给它,例如:

 CreateProcess( "C:\\windows\\system32\\cmd.exe", t_str2, ...)) 

其中t_str2"/CC:\\Temp\\sift.exe < C:\\img1.pgm > C:\\img1.key" 。 cmd.exe的实际路径可以通过读取%COMSPEC%环境变量来确定。

在第二个示例中,您正尝试使用标准输入和输出重定向,这是命令行应用程序的符号。 但是它们不是有效的程序参数。 如果你想使用重定向,你应该打开管道,并手动读取和写入输入/输出文件。 在这里,您可以找到一个示例,了解如何使用输入/输出重定向实现流程创建。

CreateProcess有一些烦人的问题,如果你还没有引用官方文档,跨Stack Exchange的旧的答案可以使这个过程有点麻烦。

  1. CreateProcess参数1大部分是可选的,对于第一个参数来说真的很奇怪。 如果你不想指定它,使用NULL ,否则你应该阅读关于如何使用参数1,而不是设置为NULL非常具体的 文档 。
  2. 如果将参数1设置为NULL ,则应用程序需要是参数2的第一部分。

再次感谢雷米清理我最初的答案怪异的行为。


此代码示例仅需要Windows上的基本VC ++编译器,并且能够在将由记事本打开的桌面上制作和存储文件。

如果这不切实际,可以使用%temp%或其他位置来放置测试文件。 该应用程序将运行,直到您关闭notepad.exe。 这也处理获取和返回退出代码。 如果你不想让它无限期地运行,直到退出,你需要更新WaitForSingleObject行。

 #include <Windows.h> int main() { STARTUPINFOA startup_info = { 0 }; LPSTARTUPINFOA p_startup_info = &startup_info; PROCESS_INFORMATION proc_info = { 0 }; LPPROCESS_INFORMATION p_proc_info = &proc_info; char command_line[] = "C:\\Windows\\System32\\cmd.exe /C notepad.exe \"%USERPROFILE%\\Desktop\\test.txt\""; bool process_created = CreateProcess( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, p_startup_info, p_proc_info ); if (!process_created) { return -3; } DWORD process_exit; WaitForSingleObject(proc_info.hThread, INFINITE); GetExitCodeProcess(p_proc_info->hProcess, &process_exit); return (int)process_exit; }