Ответ 1
Вы должны указать также имя модуля в параметрах: LPTSTR cmdArgs = "App [email protected]";
Это должна быть вся командная строка (включая argv [0]).
Здравствуйте, у меня есть следующий код, но он не работает должным образом, не могу понять, в чем проблема.
В принципе, я выполняю процесс (процесс .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 = "[email protected]";
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;
}
EDIT:. Еще одна вещь, если я передаю свой cmdArgs
следующим образом:
// a space as the first character
LPTSTR cmdArgs = " [email protected]";
Затем я получаю ошибку, затем CreateProcess возвращает TRUE
, но мой целевой процесс не выполняется.
Object reference not set to an instance of an object
Вы должны указать также имя модуля в параметрах: LPTSTR cmdArgs = "App [email protected]";
Это должна быть вся командная строка (включая argv [0]).
Если первый параметр 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 [email protected]";
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 [email protected]
[0]: echoargs.exe
[1]: [email protected]
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 [email protected]\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 [email protected]";
Из того, что я могу сказать, единственное реальное различие между ними состоит в том, что в примере Zeus аргумент dwCreationFlags установлен в значение CREATE_NEW_PROCESS_GROUP.
Попробуйте следующее:
LPTSTR cmdArgs = "[email protected]";
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 может изменять содержимое этой строки. Поэтому этот параметр не может быть указателем на постоянную память (например, константную переменную или литеральную строку). Если этот параметр является константой, функция может вызвать нарушение доступа.
Поэтому вы можете попробовать использовать LPTSTR cmdArgs = _tcsdup("[email protected]")
.
Другая проблема заключается в следующем: как целевой процесс считывает аргументы? используя argv [0] в качестве имени приложения? Затем вы также добавите имя приложения в качестве первого параметра.
Вы не выделяете память для своей строки.
Вместо:
LPTSTR cmdArgs = "[email protected]";
попробовать:
TCHAR cmdArgs[] = "[email protected]";
Изменить: затем вызовите:
CreateProcess("D:\\email\\smtp.exe", &cmdArgs[0], ...
Это создаст локальный массив в стеке, а затем передаст указатель на этот массив.
Вы можете добавить пробел как первый символ строки cmdArgs:
LPTSTR cmdArgs = " [email protected]";
По-видимому, Windows добавляет вторую строку аргумента к имени приложения, представленному первым аргументом, и результат передается в качестве аргументов командной строки для исполняемого файла. Таким образом, добавление пространства будет правильно разделять аргументы.