Я работаю в C-проекте, окружении Windows, используя WinAPI. Моя функция выполняет команду (e.g. : "dir C:\Users")
, полученную в качестве параметра, и возвращает свой вывод.
Он бежит от DLL, поэтому он не должен порождать окна cmd.exe
, что означает, что я не могу использовать _popen
. Поэтому я использую CreateProcessA
и трубу, чтобы поймать stdout.Windows CreateProcess и перенаправление вывода
Вот код:
char *runExec(char *command, int *contentLen) {
char *ret=NULL,*tmp=NULL;
DWORD readBytes;
int size=0;
char buffer[128],cmdBuf[4096];
HANDLE StdOutHandles[2];
CreatePipe(&StdOutHandles[0], &StdOutHandles[1], NULL, 4096);
STARTUPINFOA si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdOutput = StdOutHandles[1];
si.hStdError = StdOutHandles[1];
PROCESS_INFORMATION pi;
snprintf(cmdBuf,4096,"cmd /C %s", command);
if (!CreateProcessA(NULL, cmdBuf, NULL, NULL, FALSE, CREATE_NO_WINDOW | DETACHED_PROCESS, NULL, NULL, &si, &pi)) {
printf("Error createProcess : %d\n",GetLastError());
return NULL;
}
CloseHandle(StdOutHandles[1]);
printf("Before read\n");
while (ReadFile(StdOutHandles[0], buffer, 127, &readBytes, NULL)){
printf("IN WHILE\n");
buffer[readBytes] = 0;
printf("read %d bytes\n", readBytes);
size += readBytes;
tmp = (char *)realloc(ret, size + 1);
if (tmp == NULL) {
free(ret);
return NULL;
}
ret = tmp;
strncpy(ret + (size - readBytes), buffer, readBytes);
ret[size] = 0;
}
printf("Readfile returned with %d, read %d\n", GetLastError(),readBytes);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(StdOutHandles[0]);
printf("#%s#\n", ret);
return ret;
}
И выход:
Before read
Readfile returned with 109, read 0
#(null)#
Так от этого я понимаю, что:
- Мой цикл даже не выполненный один раз
- ReadFile ничего не читает и возвращает Brok ru Труба немедленно
Я прочитал различные страницы stackoverflow и MSDN, но я не могу заставить его работать.
Из документации STARTUPINFO: * Если этот флаг указан при вызове одной из функций создания процесса, ручки должны быть наследуемыми, а параметр bInheritHandles функции должен быть установлен в значение ИСТИНА. Для получения дополнительной информации см. «Наследование на ручку». * Оба требования не выполняются вашим кодом. –
Aaaaand Я не могу читать ... Спасибо за это! –