CreateProcess и аргументы командной строки - PullRequest
4 голосов
/ 28 декабря 2011

Справочная информация: Windows 7, Visual C ++ 2010 Express

Проблема: CreateProcess () продолжает возвращаться с «Недопустимым аргументом командной строки»

Объяснение: Я пишу фрагмент кода, который вызывает внешние программы, используя CreateProcess Windows API. Я получил вызов для работы с одной внешней программой:

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

Это прекрасно работает даже при том количестве данных, которое я сделал, чтобы поместить все в строки и указатели Windows. Поэтому я скопировал все искажения для CreateProcess () для другого вызова другой внешней программы:

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

По сути, что-то очень похожее, но со всеми именами переменных, которые были изменены (так как у меня эти два вызова выполняются последовательно). И вот где проблема; он не запускается и вместо этого выводит «Недопустимый аргумент командной строки:

Я переключил t_str2 на что-то немного менее сложное (так как я знаю, как работает sift.exe), и я получил тот же результат. То же самое происходит, когда я бегу просто просеять, а не конвертировать.

Вопрос: Что может быть причиной этой проблемы? Что я мог сделать для дальнейшей отладки этой проблемы? Любые предложения по альтернативам методам, которые я использую? Любая помощь приветствуется. Я могу предоставить дополнительный код, но он довольно прост, и с ним не так уж много.

Ответы [ 3 ]

9 голосов
/ 28 декабря 2011

Вы не можете напрямую использовать операторы перенаправления командной строки с CreateProcess(). Вы должны создать экземпляр cmd.exe и передать вместо него операторы, например:

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

Где t_str2 равно "/C C:\\Temp\\sift.exe < C:\\img1.pgm > C:\\img1.key". Фактический путь к cmd.exe можно определить, прочитав переменную окружения %COMSPEC%.

4 голосов
/ 28 декабря 2011

Во втором примере вы пытаетесь использовать стандартные перенаправления ввода и вывода, которые являются обозначениями приложения командной строки.Но они не являются действительными аргументами программы.Если вы хотите использовать перенаправление, вы должны открыть каналы и вручную читать и записывать из / во входные / выходные файлы. Здесь вы можете найти пример того, как реализовать создание процесса с перенаправлением ввода / вывода.

0 голосов
/ 11 августа 2017

CreateProcess имеет некоторые неприятные ошибки, и более старые ответы в Stack Exchange могут сделать этот процесс несколько проблематичным, если вы также не ссылаетесь на официальную документацию.

  1. Параметр 1 для CreateProcess по большей части необязателен, что действительно странно для первого параметра. Если вы не хотите указывать его, используйте NULL, в противном случае вам следует прочитать очень специфическую документацию о том, как использовать параметр 1, если для него не установлено значение NULL.
  2. Если для параметра 1 установлено значение NULL, приложение должно быть первой частью параметра 2.

Еще раз спасибо Реми за разъяснение странного поведения в моем первоначальном ответе.


Для этого примера кода требуется только базовый компилятор VC ++ в Windows и возможность создавать и хранить на рабочем столе файл, который будет открыт Блокнотом.

Если это нецелесообразно, не стесняйтесь использовать %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;
}
...