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;
}

РЕДАКТИРОВАТЬ: Эй, еще одна вещь, если я передам cmdArgs как это:

// a space as the first character
LPTSTR cmdArgs = " name@example.com";

Тогда я получаю ошибку, затем CreateProcess возвращает TRUE но мой целевой процесс не выполняется.

Object reference not set to an instance of an object

8 ответов

Вы должны также указать имя модуля в параметрах: LPTSTR cmdArgs = "App name@example.com";Это должна быть вся командная строка (включая argv[0]).

Если первый параметр CreateProcess() не NULL, он будет использовать это, чтобы найти изображение для запуска.

Если он равен NULL, он будет анализировать 2-й аргумент, чтобы попытаться запустить исполняемый файл с 1-го токена.

В любом случае среда выполнения 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;
}

Вот вывод, который я получаю из этой программы:

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

Yohoo!

Не похоже, что вы используете 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, указывает модуль для выполнения, а строка с нулевым символом в конце, на которую указывает lpCommandLine, указывает командную строку. Новый процесс может использовать GetCommandLine для получения всей командной строки. Консольные процессы, написанные на C, могут использовать аргументы argc и argv для разбора командной строки. Поскольку argv[0] является именем модуля, программисты на C обычно повторяют имя модуля в качестве первого токена в командной строке.

Так что в вашем случае это нужно в качестве аргумента команды и, вероятно, следует передать NULL для первого параметра, чтобы получить поведение, которое вы хотите.

// NOTE THE Null-Terminated string too!
LPTSTR cmdArgs = "D:\\email\\smtp.exe name@example.com\0";

Ниже приведена сокращенная версия кода, используемого в 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);
}

Командой pszCommand будет полный путь к исполняемому файлу, имя файла и аргументы, например:

pszCommand = "D:\\email\\smtp.exe name@example.com";

Из того, что я могу сказать, единственное реальное различие между ними заключается в том, что в примере Zeus аргументу dwCreationFlags присвоено значение CREATE_NEW_PROCESS_GROUP.

Вы можете добавить пробел в качестве первого символа строки cmdArgs:

LPTSTR cmdArgs = " name@example.com";

Очевидно, что Windows добавляет вторую строку аргумента к имени приложения, представленному первым аргументом, и результат передается как аргументы командной строки в исполняемый файл. Таким образом, добавление пробела будет правильно разделять аргументы.

Попробуй это:

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

Версия этой функции Unicode, CreateProcessW, может изменять содержимое этой строки. Следовательно, этот параметр не может быть указателем на постоянную память (такую ​​как переменная const или литеральная строка). Если этот параметр является константной строкой, функция может вызвать нарушение прав доступа.

Поэтому вы можете попробовать использовать LPTSTR cmdArgs = _tcsdup("name@example.com"),

Другая проблема: как целевой процесс читает аргументы? используя argv[0] в качестве имени приложения? Затем вы должны добавить имя приложения в качестве первого параметра тоже.

Вы не выделяете память для своей строки.

Вместо:

LPTSTR cmdArgs = "name@example.com";

пытаться:

TCHAR cmdArgs[] = "name@example.com";

Изменить: затем позвоните:

 CreateProcess("D:\\email\\smtp.exe", &cmdArgs[0], ...

Это создаст локальный массив в стеке и затем передаст указатель на этот массив.

Другие вопросы по тегам