windows CreateProcess 和命令行参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8649212/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:44:53  来源:igfitidea点击:

CreateProcess and command line arguments

c++windowscommand-line-argumentscreateprocess

提问by user850275

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. I've gotten the call to work with one external program so far:

说明:我正在编写一段使用 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). 

This works perfectly even with the amount of data-mangling I did to push everything into the Windows strings and pointers. So I copied all of the mangling for CreateProcess() for another call to a different external program:

即使我为将所有内容推送到 Windows 字符串和指针中所做的大量数据处理,这也能完美运行。因此,我复制了 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". Of course, this command works fine in the command prompt, but not in my code.

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

I switched t_str2 to something else a little less complicated(since I know how sift.exe works) and I get the same result. Same thing happens when I run just sift and not convert.

我将 t_str2 切换到其他稍微不那么复杂的东西(因为我知道 sift.exe 是如何工作的)并且我得到了相同的结果。当我只运行 sift 而不是转换时,也会发生同样的事情。

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.

问题:什么可能导致这个问题?我能做些什么来进一步调试这个问题?关于我正在使用的方法的替代方法有什么建议吗?任何帮助表示赞赏。我可以提供更多代码,但它非常简单,而且不会出错。

回答by Remy Lebeau

You cannot use command-line redirection operators with CreateProcess()directly. You have to spawn an instance of cmd.exe and pass the operators to it instead, eg:

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

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

Where t_str2is "/C C:\\Temp\\sift.exe < C:\\img1.pgm > C:\\img1.key". The actual path to cmd.exe can be determined by reading the %COMSPEC%environment variable.

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

回答by Eugene

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. Hereyou can find an example how to implement pthe process creation with input/output redirections.

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

回答by kayleeFrye_onDeck

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

Thanks again to Remy for clearing up the weird behavior on my initial answer.

再次感谢 Remy 在我最初的回答中清除了奇怪的行为。



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. The app will run until you close 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 WaitForSingleObjectline.

如果这不切实际,请随意使用%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;
}