#c #windows #winapi #cmd #process
#c #Windows #winapi #cmd #процесс
Вопрос:
Я использую CreateProcess
для вызова cmd.exe
пользовательскую команду:
#include <Windows.h>
#include <stdio.h>
int main() {
HANDLE stdout_w = NULL;
HANDLE stdout_r = NULL;
SECURITY_ATTRIBUTES sattr = { 0 };
sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
sattr.bInheritHandle = TRUE;
if (!CreatePipe(amp;stdout_r, amp;stdout_w, amp;sattr, 0))
return EXIT_FAILURE;
SetHandleInformation(stdout_r, HANDLE_FLAG_INHERIT, 0);
PROCESS_INFORMATION pi = { 0 };
STARTUPINFOA si = { 0 };
si.cb = sizeof(si);
si.hStdError = stdout_w;
si.hStdOutput = stdout_w;
si.dwFlags = STARTF_USESTDHANDLES;
char command[256];
strcpy_s(command, _countof(command), "cmd /S /C "ag "ch""");
if (!CreateProcessA(NULL, command, NULL, NULL, TRUE, 0, NULL, "c:/users/lisa/projects/monkey", amp;si, amp;pi))
return EXIT_FAILURE;
while (true) {
switch (WaitForSingleObject(pi.hProcess, 0)) {
case WAIT_TIMEOUT:
break;
case WAIT_OBJECT_0:
return EXIT_SUCCESS;
default:
return EXIT_FAILURE;
}
}
}
Здесь я вызываю cmd.exe
с помощью команды ag "ch"
. ( ag
это утилита, которая ищет в файлах строку, вроде как grep
.)
Проблема в том, что она зависает — цикл в конце выполняется вечно, и я вижу, что созданный cmd.exe
процесс остается открытым в диспетчере задач. Пара странных вещей об этом:
- Когда я запускаю
cmd.exe /S /C "ag "ch""
непосредственно из командной строки, он работает нормально и завершается, как ожидалось. - Когда я меняю код для запуска
ag "chi"
(т. Е. Для поиска большей подстроки), он завершается, как и ожидалось. Кроме того, когда я меняю каталог на папку без каких-либо файлов, он также завершается, как и ожидалось. Это заставляет меня думать, что проблема в том, что выводag
слишком длинный. - Когда я напрямую передаю
ag "ch"
командуCreateProcess
, она завершается, как и ожидалось. (К сожалению, я не могу этого сделать, потому что это часть более крупной утилиты, которая позволяет мне запускать любую пакетную команду из C, в том числе с использованием каналов.)
У кого-нибудь есть идеи, что здесь происходит?
Комментарии:
1. Я бы ожидал, что ваша текстовая строка команды будет
"cmd /S /C ag "ch""
, а не"cmd /S /C "ag "ch"""
. Мне кажется, что слишком много двойных кавычек приводит к командной строкеcmd /S /C "ag "ch""
и тому, что вы хотитеcmd /S /c ag "ch"
.2. почему вы запускаете cmd вместо прямого ag.exe ? где вы используете перенаправленный вывод? для чего вы его перенаправляете? вы ничего не читаете и не записываете в каналы
3. Этот код удален из более крупного служебного класса, который позволяет мне вызывать любую пакетную команду (например
ag ch | filter
) и считывать выходные данные. Этот код предназначен только для демонстрации проблемы.4. Канал заполнен, поэтому программа не может записать в него больше данных. Вы должны прочитать уже записанные данные из канала, чтобы освободить место для большего.
5. Почему вы вызываете
WaitForSingleObject()
в замкнутом цикле с таймаутом 0 мс? Полностью избавьтесь от такого цикла опроса и просто вызовитеWaitForSingleObject()
один раз сINFINITE
таймаутом.