CreateProcess不传递命令行参数

aki*_*kif 26 c++ winapi createprocess

您好我有以下代码,但它没有按预期工作,无法弄清楚问题是什么.

基本上,我正在执行一个进程(一个.NET进程)并传递它的命令行参数,它由CreateProcess()成功执行但CreateProcess()没有传递命令行参数

我在这做错了什么?

int main(int argc, char* argv[])
{
    PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter

    STARTUPINFO StartupInfo; //This is an [in] parameter

    ZeroMemory(&StartupInfo, sizeof(StartupInfo));
    StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field

    LPTSTR cmdArgs = "name@example.com";

    if(CreateProcess("D:\\email\\smtp.exe", cmdArgs, 
        NULL,NULL,FALSE,0,NULL,
        NULL,&StartupInfo,&ProcessInfo))
    { 
        WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);

        printf("Yohoo!");
    }  
    else
    {
        printf("The process could not be started...");
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:嘿,还有一件事,如果我这样通过我cmdArgs:

// a space as the first character
LPTSTR cmdArgs = " name@example.com";
Run Code Online (Sandbox Code Playgroud)

然后我得到错误,然后CreateProcess返回TRUE但我的目标进程没有执行.

Object reference not set to an instance of an object
Run Code Online (Sandbox Code Playgroud)

EFr*_*aim 24

应该指定在参数模块名称:LPTSTR cmdArgs = "App name@example.com"; 它应该是整个命令行(包括的argv [0]).

  • 确切地说,许多程序从argv [1]的参数评估开始,因为argv [0]通常包含模块名称.如果模块名称不在命令行中,则会丢失.最终你失去了第一个参数,这是一个大问题,花了我太多时间来弄明白. (5认同)
  • 我不得不说MSDN对此不太清楚:"因为`argv [0]`是模块名称,C程序员通常会重复模块名称作为命令行中的第一个标记." 并且"如果`lpApplicationName`为NULL,则命令行的第一个以空格分隔的标记指定模块名称." 后者似乎不适用,因为提供了`lpApplicationName`. (3认同)

Mic*_*urr 19

如果第一个参数CreateProcess()为非NULL,它将使用它来定位要启动的图像.

如果它为NULL,它将解析第二个参数以尝试从第一个令牌启动可执行文件.

在任何一种情况下,C运行时都将使用第二个参数来填充argv数组.所以该参数的第一个标记出现在argv[0].

您可能需要以下内容(我已将smtp.exe程序更改为echoargs.exe - 一个简单的实用程序,我必须帮助弄清楚这种问题):

int main(int argc, char* argv[])
{
    PROCESS_INFORMATION ProcessInfo; //This is what we get as an [out] parameter

    STARTUPINFO StartupInfo; //This is an [in] parameter
    char cmdArgs[] = "echoargs.exe name@example.com";

    ZeroMemory(&StartupInfo, sizeof(StartupInfo));
    StartupInfo.cb = sizeof StartupInfo ; //Only compulsory field


    if(CreateProcess("C:\\util\\echoargs.exe", cmdArgs, 
        NULL,NULL,FALSE,0,NULL,
        NULL,&StartupInfo,&ProcessInfo))
    { 
        WaitForSingleObject(ProcessInfo.hProcess,INFINITE);
        CloseHandle(ProcessInfo.hThread);
        CloseHandle(ProcessInfo.hProcess);

        printf("Yohoo!");
    }  
    else
    {
        printf("The process could not be started...");
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是我从该程序得到的输出:

echoargs.exe name@example.com
[0]: echoargs.exe
[1]: name@example.com

Yohoo!
Run Code Online (Sandbox Code Playgroud)


Ray*_*yes 5

看起来您没有正确使用CreateProcess,请参阅http://msdn.microsoft.com/en-us/library/ms682425%28VS.85%29.aspx.

  • 要执行的命令行.此字符串的最大长度为32,768个字符,包括Unicode终止空字符.如果lpApplicationName为NULL,则lpCommandLine的模块名称部分限制为MAX_PATH字符.

  • lpCommandLine参数可以为NULL.在这种情况下,该函数使用lpApplicationName指向的字符串作为命令行.

  • 如果lpApplicationName和lpCommandLine都是非NULL,则lpApplicationName指向的以null结尾的字符串指定要执行的模块,lpCommandLine指向的以null结尾的字符串指定命令行.新进程可以使用GetCommandLine来检索整个命令行.用C编写的控制台进程可以使用argc和argv参数来解析命令行.因为argv [0]是模块名称,所以C程序员通常会重复模块名称作为命令行中的第一个标记.

所以在你的情况下,你需要这个作为命令参数,并且应该为第一个参数传递NULL以获得你想要的行为.

// NOTE THE Null-Terminated string too!
LPTSTR cmdArgs = "D:\\email\\smtp.exe name@example.com\0";
Run Code Online (Sandbox Code Playgroud)

  • 最后的代码片段定义了一个带有两个空终止符的字符串 - 无需显式放入第二个. (4认同)

jus*_*sij 5

以下是Zeus IDE用于运行外部进程的代码的简化版本:

bool createProcess(const char *pszTitle, const char *pszCommand)
{
  STARTUPINFO StartInfo;

  memset(&StartInfo, 0, sizeof(StartInfo));

  StartInfo.cb      = sizeof(StartInfo);
  StartInfo.lpTitle = (pszTitle) ? (char *)pszTitle : (char *)pszCommand;

  StartInfo.wShowWindow = SW_NORMAL;
  StartInfo.dwFlags    |= STARTF_USESHOWWINDOW;

  if (CreateProcess(0, (char *)pszCommand, 
                    0, 0, TRUE,
                    CREATE_NEW_PROCESS_GROUP, 0, 0, 
                    &StartInfo, &ProcessInfo))
  {
    lErrorCode = 0;
  }
  else
  {
    lErrorCode = GetLastError();
  }

  return (lErrorCode == 0);
}
Run Code Online (Sandbox Code Playgroud)

pszCommand将是完整的可执行文件的路径和文件名和参数,以便例如:

pszCommand = "D:\\email\\smtp.exe name@example.com";
Run Code Online (Sandbox Code Playgroud)

据我所知,两者之间唯一真正的区别是,在Zeus示例中,dwCreationFlags参数设置为CREATE_NEW_PROCESS_GROUP值.


aJ.*_*aJ. 3

尝试这个:

LPTSTR cmdArgs = "name@example.com";
CString szcmdline("D:\\email\\smtp.exe");
szcmdline += _T(" ") + cmdArgs ;

//Leave first param empty and pass path + argms in 
    if(CreateProcess(NULL, szcmdline, second
Run Code Online (Sandbox Code Playgroud)