Вызов консольного приложения из программы на Delphi
Для вызова внешнего приложения из программы на Delphi обычно используется функция WinAPI CreateProcess. Но как получить то, что это приложение выводит в консоль, и, например, отобразить в логе программы? Варианта два. Первый: пере-направить вывод консольного приложения в файл и потом прочитать этот файл. Однако, создавать временный файл не охота. А кроме того, такой способ не всегда хорошо работает. Есть другой способ - использовать пайпы (pipes). Ниже приведен код процедуры RunDosCommand на Delphi, который использует этот способ. Весь вывод на консоль записывается в AMemo: TMemo.
functionRunDosCommand(ACmdString: String; AMemo: TMemo; AReadPipe, AWritePipe: THandle): Boolean; const ReadBuffer = 4200; var Security : TSecurityAttributes; ReadPipe, WritePipe: THandle; start : TStartUpInfo; ProcessInfo : TProcessInformation; Buffer : Pchar; BytesRead : DWord; begin Result := False; if AMemo <> nilthen begin AMemo.SelStart := Length(AMemo.Text); AMemo.SelText := ACmdString + #13#10; AMemo.SelStart := Length(AMemo.Text); Application.ProcessMessages; end; ReadPipe := AReadPipe; WritePipe := AWritePipe; with Security do begin nLength := SizeOf(TSecurityAttributes); bInheritHandle := true; lpSecurityDescriptor := nil; end; if (ReadPipe = 0) and (WritePipe = 0) then begin ifnot CreatePipe(ReadPipe, WritePipe, @Security, 0) then begin ReadPipe := 0; WritePipe := 0; end; end; if (ReadPipe <> 0) or (WritePipe <> 0) then begin if AMemo <> nilthen begin Buffer := AllocMem(ReadBuffer + 1); end; FillChar(Start, Sizeof(Start), #0); start.cb := SizeOf(start) ; start.hStdOutput := WritePipe; start.hStdError := WritePipe; start.hStdInput := ReadPipe; start.dwFlags := STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW; start.wShowWindow := SW_HIDE; if CreateProcess(nil, PChar(ACmdString), @Security, @Security, true, NORMAL_PRIORITY_CLASS, nil, nil, start, ProcessInfo) then begin WaitForSingleObject(ProcessInfo.hProcess, INFINITE); if AMemo <> nilthen begin BytesRead := 0; ReadFile(ReadPipe, Buffer[0], ReadBuffer, BytesRead, nil); Buffer[BytesRead] := #0; AMemo.SelStart := Length(AMemo.Text); AMemo.SelText := String(Buffer); AMemo.SelStart := Length(AMemo.Text); Application.ProcessMessages; end; Result := True; endelse if AMemo <> nilthen begin AMemo.SelStart := Length(AMemo.Text); AMemo.SelText :='Command failed.'#13#10; AMemo.SelStart := Length(AMemo.Text); Application.ProcessMessages; end; if AMemo <> nilthen begin FreeMem(Buffer); end; CloseHandle(ProcessInfo.hProcess); CloseHandle(ProcessInfo.hThread); if (AReadPipe = 0) and (AWritePipe = 0) then begin CloseHandle(ReadPipe); CloseHandle(WritePipe); end; end; end;
=== Перепечатка материалов блога разрешается с обязательной ссылкой на blog.coolsoftware.ru