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], ...
Это создаст локальный массив в стеке и затем передаст указатель на этот массив.