简体   繁体   English

CreateProcess和命令行参数

[英]CreateProcess and command line arguments

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

Problem: CreateProcess() keeps returning with 'Invalid command line argument' 问题: CreateProcess()通过'无效的命令行参数'继续返回

Explanation: I'm writing a piece of code that calls external programs using the Windows API's CreateProcess. 说明:我正在编写一段使用Windows API的CreateProcess调用外部程序的代码。 I've gotten the call to work with one external program so far: 到目前为止,我已接到使用一个外部程序的电话:

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

This works perfectly even with the amount of data-mangling I did to push everything into the Windows strings and pointers. 即使我将所有数据都推送到Windows字符串和指针中,我也可以完美地工作。 So I copied all of the mangling for CreateProcess() for another call to a different external program: 所以我复制了CreateProcess()的所有修改,以便对另一个外部程序进行另一次调用:

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

Basically, something very similar, but with all the variable names changed (since I have these two calls running serial). 基本上,一些非常相似,但所有变量名称都已更改(因为我有两个调用运行串行)。 And this is where the problem is; 这就是问题所在; this doesn't run, and, instead, prints out "Invalid command line argument: < C:\\img1.pgm". 这不会运行,而是打印出“无效的命令行参数:<C:\\ img1.pgm”。 Of course, this command works fine in the command prompt, but not in my code. 当然,这个命令在命令提示符下工作正常,但在我的代码中没有。

I switched t_str2 to something else a little less complicated(since I know how sift.exe works) and I get the same result. 我将t_str2切换到其他一些不太复杂的东西(因为我知道sift.exe如何工作),我得到了相同的结果。 Same thing happens when I run just sift and not convert. 当我只进行筛选而不是转换时,会发生同样的事情。

Question: What could be causing this problem? 问题:可能导致此问题的原因是什么? What could I do to further debug this problem? 我该怎么做才能进一步调试这个问题? Any suggestions on alternatives to the methods I'm using? 关于我正在使用的方法的替代方案的任何建议? Any help is appreciated. 任何帮助表示赞赏。 I can provide further code, but It's pretty straight forward, and not much could go wrong with it. 我可以提供进一步的代码,但它非常直接,并没有太多可能出错。

You cannot use command-line redirection operators with CreateProcess() directly. 您不能直接使用命令行重定向运算符和CreateProcess() You have to spawn an instance of cmd.exe and pass the operators to it instead, eg: 您必须生成cmd.exe的实例并将操作符传递给它,例如:

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

Where t_str2 is "/CC:\\\\Temp\\\\sift.exe < C:\\\\img1.pgm > C:\\\\img1.key" . 其中t_str2"/CC:\\\\Temp\\\\sift.exe < C:\\\\img1.pgm > C:\\\\img1.key" The actual path to cmd.exe can be determined by reading the %COMSPEC% environment variable. 可以通过读取%COMSPEC%环境变量来确定cmd.exe的实际路径。

In the second example you are trying to use standard input and out redirections, which are notations of the command line application. 在第二个示例中,您尝试使用标准输入和重定向,这是命令行应用程序的符号。 But they are not valid program arguments. 但它们不是有效的程序参数。 If you want use redirection you should open pipes and manualy read and write from/to input/output files. 如果你想使用重定向,你应该打开管道并手动读/写输入/输出文件。 Here you can find an example how to implement pthe process creation with input/output redirections. 在这里,您可以找到如何使用输入/输出重定向实现流程创建的示例。

CreateProcess has some annoying gotchas, and the older answers across Stack Exchange can make that process somewhat troublesome if you're not also referencing the official documentation. CreateProcess有一些烦人的陷阱,如果你还没有引用官方文档,那么Stack Exchange中较旧的答案可能会使这个过程有点麻烦。

  1. Parameter 1 for CreateProcess is for the most part optional, which is really weird for a first parameter. CreateProcess参数1大部分是可选的,这对于第一个参数来说真的很奇怪。 If you don't want to specify it, use NULL , otherwise you should read the very specific documentation on how to use parameter 1 when not setting it to NULL . 如果您不想指定它,请使用NULL ,否则您应该阅读非特定 文档 ,了解如何在不将参数1设置为NULL时使用参数1。
  2. If setting parameter 1 to NULL , the application needs to be the first part of parameter 2. 如果将参数1设置为NULL ,则应用程序需要是参数2的第一部分。

Thanks again to Remy for clearing up the weird behavior on my initial answer. 再次感谢雷米清除我最初答案中的奇怪行为。


This code sample only requires a basic VC++ compiler on Windows and the ability to make and store a file on the Desktop that will be opened by Notepad. 此代码示例仅需要Windows上的基本VC ++编译器,并且能够在桌面上创建和存储将由记事本打开的文件。

If that's not practical, feel free to use %temp% or some other location for placing the test file. 如果这不实用,请随意使用%temp%或其他位置放置测试文件。 The app will run until you close notepad.exe. 该应用程序将一直运行,直到您关闭notepad.exe。 This also handles getting and returning the exit code. 这也处理获取和返回退出代码。 If you don't want it to run indefinitely until exit, you'll need to update the WaitForSingleObject line. 如果您不希望它在退出之前无限期运行,则需要更新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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM