Advertisement
Guest User

ExecuteConsoleProcess

a guest
May 2nd, 2016
259
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 4.72 KB | None | 0 0
  1. function ExecuteConsoleProcess(const FileName,Directory: string; TimeOutSec: integer;
  2.                                var StdOutput:AnsiString; CallBack:TConsoleOutputCallback = nil): boolean;
  3. var
  4.   outLength  :Cardinal;
  5.   SecAttr    :TSecurityAttributes;
  6.   PipeRead   :THandle;
  7.   PipeWriteOut  :THandle;
  8.   PipeWriteErr  :THandle;
  9.   PipeWriteIn  :THandle;
  10.   StartInf   :TStartupInfo;
  11.   ProcInf    :TProcessInformation;
  12.   Buf        :TConsoleBuffer;//array[0..255] of byte;
  13.   BufLength  :Cardinal;
  14.   Bytes      :DWord;
  15.   cmdLine    :PChar;
  16.   Dir        :PChar;
  17.   LastErr    :DWORD;
  18.   WaitResult :Cardinal;
  19. begin
  20.   Result := False;
  21.  
  22.  //Упреждаем фигню с CreateProcessW, которая пишет в буферы строк, ей передаваемых
  23.   GetMem(cmdLine,MAX_PATH *SizeOf(Char));
  24.   StrPCopy(cmdLine,FileName);
  25.  
  26.   GetMem(Dir,MAX_PATH *SizeOf(Char));
  27.   StrPCopy(Dir, Directory);
  28.  
  29.   PipeRead  := INVALID_HANDLE_VALUE;
  30.   PipeWriteOut := INVALID_HANDLE_VALUE;
  31.   PipeWriteErr := INVALID_HANDLE_VALUE;
  32.  
  33.  
  34.  
  35.   SecAttr.nLength := SizeOf(SecAttr);
  36.   SecAttr.bInheritHandle := TRUE;
  37.   SecAttr.lpSecurityDescriptor := nil;
  38.  
  39. try
  40.  try
  41.   // Создаем пайпы
  42.   if not CreatePipe(PipeRead,  PipeWriteOut,  @SecAttr, 0 ) then RaiseLastOSError;
  43.  
  44.  
  45. //   Дублицируем хендлы
  46.   if not DuplicateHandle(GetCurrentProcess, PipeWriteOut, GetCurrentProcess,
  47.            @PipeWriteErr, 0, True, DUPLICATE_SAME_ACCESS) then RaiseLastOSError;
  48.  
  49.   if not DuplicateHandle(GetCurrentProcess,PipeWriteOut, GetCurrentProcess,
  50.            @PipeWriteIn, 0, True, DUPLICATE_SAME_ACCESS) then RaiseLastOSError;
  51.  
  52.  // Идиотизм вызванный утилитой ХCOPY которая не работает без включения  bInheritHandle
  53.  
  54.  
  55.  
  56.   ZeroMemory(@StartInf,Sizeof(TStartupInfo));
  57.  
  58.   StartInf.cb := SizeOf(TStartupInfo);
  59.   StartInf.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
  60.  
  61.   StartInf.wShowWindow := SW_HIDE;// запустить невидимо
  62.  
  63.   StartInf.hStdInput  := PipeWriteIn; // Идиотизм вызванный утилитой ХCOPY которая не работает без редиректа stdin если мы редиректим stdout
  64.   // GetStdHandle(STD_INPUT_HANDLE); // stdin оставляем консоли свой
  65.   StartInf.hStdOutput := PipeWriteOut; // stdout и stderr пишем в наш пайп.
  66.   StartInf.hStdError  := PipeWriteErr;
  67.  
  68.   //Запускаем
  69.   if not CreateProcess(nil, PChar(cmdLine), nil,
  70.                        nil, True, NORMAL_PRIORITY_CLASS,
  71.                        nil, PChar(Dir), StartInf, ProcInf) then RaiseLastOSError;
  72.  
  73.  
  74.   // Закрываем хендл записи в STDOUT чтобы прочитать консольный вывод
  75.  
  76.  
  77.   CloseHandle(PipeWriteOut);
  78.   CloseHandle(PipeWriteErr);
  79.   CloseHandle(PipeWriteIn);
  80.  
  81.   PipeWriteOut := INVALID_HANDLE_VALUE;
  82.   PipeWriteErr := INVALID_HANDLE_VALUE;
  83.   PipeWriteIn  := INVALID_HANDLE_VALUE;
  84.  
  85.  
  86.   // Читаем наш пайп
  87.   BufLength := SizeOf(Buf);
  88.  
  89.   StdOutput := '';
  90.   while True do
  91.   begin
  92.     Bytes := 0;
  93.     if not ReadFile(PipeRead, Buf, BufLength, Bytes, nil) then
  94.     begin
  95.       LastErr := GetLastError;
  96.       // Если в пайпе нет воды выходим, иначе показываем ошибку
  97.       if LastErr = ERROR_BROKEN_PIPE then Break else RaiseLastOSError;
  98.     end;
  99.     if Bytes = 0 then Break;  // Если нет данных выходим
  100.     outLength := Length(StdOutput);
  101.     SetLength(StdOutput, outLength + Bytes);
  102.     Move(Buf[0],StdOutput[outLength + 1], Bytes);  //Подозрительная тема, но лучшей пока нет.
  103.     if Assigned(CallBack) then
  104.     begin
  105.       CallBack(Buf, Bytes);
  106.     end;
  107.    end;
  108.  
  109.  
  110.   Result := true;
  111.   Exit;
  112.  
  113.   except on E:Exception do
  114.    begin
  115.    if ProcInf.hProcess = INVALID_HANDLE_VALUE then raise;
  116.    CloseHandle(ProcInf.hThread);
  117.    WaitResult := WaitForSingleObject(ProcInf.hProcess, 1000);
  118.    CloseHandle(ProcInf.hProcess);
  119.    if WaitResult <> WAIT_OBJECT_0 then
  120.    begin
  121.      ProcInf.hProcess := OpenProcess(PROCESS_TERMINATE, FALSE, ProcInf.dwProcessId);
  122.      if ProcInf.hProcess <> 0 then
  123.      begin
  124.        TerminateProcess(ProcInf.hProcess, 0);
  125.        CloseHandle(ProcInf.hProcess);
  126.      end;
  127.    end;
  128.  
  129.    raise;
  130.    end;
  131.   end;
  132.  
  133.  finally
  134.    if PipeRead <> INVALID_HANDLE_VALUE then CloseHandle(PipeRead);
  135.    if PipeWriteOut <> INVALID_HANDLE_VALUE then CloseHandle(PipeWriteOut);
  136.    if PipeWriteErr <> INVALID_HANDLE_VALUE then CloseHandle(PipeWriteErr);
  137.    if PipeWriteIn <> INVALID_HANDLE_VALUE then CloseHandle(PipeWriteIn);
  138.    CloseHandle(ProcInf.hProcess);
  139.    CloseHandle(ProcInf.hThread);
  140.  end;
  141. end;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement