Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function ExecuteConsoleProcess(const FileName,Directory: string; TimeOutSec: integer;
- var StdOutput:AnsiString; CallBack:TConsoleOutputCallback = nil): boolean;
- var
- outLength :Cardinal;
- SecAttr :TSecurityAttributes;
- PipeRead :THandle;
- PipeWriteOut :THandle;
- PipeWriteErr :THandle;
- PipeWriteIn :THandle;
- StartInf :TStartupInfo;
- ProcInf :TProcessInformation;
- Buf :TConsoleBuffer;//array[0..255] of byte;
- BufLength :Cardinal;
- Bytes :DWord;
- cmdLine :PChar;
- Dir :PChar;
- LastErr :DWORD;
- WaitResult :Cardinal;
- begin
- Result := False;
- //Упреждаем фигню с CreateProcessW, которая пишет в буферы строк, ей передаваемых
- GetMem(cmdLine,MAX_PATH *SizeOf(Char));
- StrPCopy(cmdLine,FileName);
- GetMem(Dir,MAX_PATH *SizeOf(Char));
- StrPCopy(Dir, Directory);
- PipeRead := INVALID_HANDLE_VALUE;
- PipeWriteOut := INVALID_HANDLE_VALUE;
- PipeWriteErr := INVALID_HANDLE_VALUE;
- SecAttr.nLength := SizeOf(SecAttr);
- SecAttr.bInheritHandle := TRUE;
- SecAttr.lpSecurityDescriptor := nil;
- try
- try
- // Создаем пайпы
- if not CreatePipe(PipeRead, PipeWriteOut, @SecAttr, 0 ) then RaiseLastOSError;
- // Дублицируем хендлы
- if not DuplicateHandle(GetCurrentProcess, PipeWriteOut, GetCurrentProcess,
- @PipeWriteErr, 0, True, DUPLICATE_SAME_ACCESS) then RaiseLastOSError;
- if not DuplicateHandle(GetCurrentProcess,PipeWriteOut, GetCurrentProcess,
- @PipeWriteIn, 0, True, DUPLICATE_SAME_ACCESS) then RaiseLastOSError;
- // Идиотизм вызванный утилитой ХCOPY которая не работает без включения bInheritHandle
- ZeroMemory(@StartInf,Sizeof(TStartupInfo));
- StartInf.cb := SizeOf(TStartupInfo);
- StartInf.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
- StartInf.wShowWindow := SW_HIDE;// запустить невидимо
- StartInf.hStdInput := PipeWriteIn; // Идиотизм вызванный утилитой ХCOPY которая не работает без редиректа stdin если мы редиректим stdout
- // GetStdHandle(STD_INPUT_HANDLE); // stdin оставляем консоли свой
- StartInf.hStdOutput := PipeWriteOut; // stdout и stderr пишем в наш пайп.
- StartInf.hStdError := PipeWriteErr;
- //Запускаем
- if not CreateProcess(nil, PChar(cmdLine), nil,
- nil, True, NORMAL_PRIORITY_CLASS,
- nil, PChar(Dir), StartInf, ProcInf) then RaiseLastOSError;
- // Закрываем хендл записи в STDOUT чтобы прочитать консольный вывод
- CloseHandle(PipeWriteOut);
- CloseHandle(PipeWriteErr);
- CloseHandle(PipeWriteIn);
- PipeWriteOut := INVALID_HANDLE_VALUE;
- PipeWriteErr := INVALID_HANDLE_VALUE;
- PipeWriteIn := INVALID_HANDLE_VALUE;
- // Читаем наш пайп
- BufLength := SizeOf(Buf);
- StdOutput := '';
- while True do
- begin
- Bytes := 0;
- if not ReadFile(PipeRead, Buf, BufLength, Bytes, nil) then
- begin
- LastErr := GetLastError;
- // Если в пайпе нет воды выходим, иначе показываем ошибку
- if LastErr = ERROR_BROKEN_PIPE then Break else RaiseLastOSError;
- end;
- if Bytes = 0 then Break; // Если нет данных выходим
- outLength := Length(StdOutput);
- SetLength(StdOutput, outLength + Bytes);
- Move(Buf[0],StdOutput[outLength + 1], Bytes); //Подозрительная тема, но лучшей пока нет.
- if Assigned(CallBack) then
- begin
- CallBack(Buf, Bytes);
- end;
- end;
- Result := true;
- Exit;
- except on E:Exception do
- begin
- if ProcInf.hProcess = INVALID_HANDLE_VALUE then raise;
- CloseHandle(ProcInf.hThread);
- WaitResult := WaitForSingleObject(ProcInf.hProcess, 1000);
- CloseHandle(ProcInf.hProcess);
- if WaitResult <> WAIT_OBJECT_0 then
- begin
- ProcInf.hProcess := OpenProcess(PROCESS_TERMINATE, FALSE, ProcInf.dwProcessId);
- if ProcInf.hProcess <> 0 then
- begin
- TerminateProcess(ProcInf.hProcess, 0);
- CloseHandle(ProcInf.hProcess);
- end;
- end;
- raise;
- end;
- end;
- finally
- if PipeRead <> INVALID_HANDLE_VALUE then CloseHandle(PipeRead);
- if PipeWriteOut <> INVALID_HANDLE_VALUE then CloseHandle(PipeWriteOut);
- if PipeWriteErr <> INVALID_HANDLE_VALUE then CloseHandle(PipeWriteErr);
- if PipeWriteIn <> INVALID_HANDLE_VALUE then CloseHandle(PipeWriteIn);
- CloseHandle(ProcInf.hProcess);
- CloseHandle(ProcInf.hThread);
- end;
- end;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement