FAQ » Win API

Jak wykonać polecenie systemowe i pobrać dane ze strumienia wyjściowego

Poniższa funkcja System() wykonuje obie operacje:

uses Windows;
 
function System(Cmd: string): string;
var
  TmpFn: string;
  Tmp: Cardinal;
  Buf: array[0..8191] of Char;
  Hnd: THandle;
  SI: TStartupInfo;
  SA: TSecurityAttributes;
  PI: TProcessInformation;
begin
  Result := '';
  GetTempPath(SizeOf(Buf), Buf);
  GetTempFileName(Buf, 'ABC', 0, Buf);
    TmpFn := string(Buf);
  Cmd := '%ComSpec% /c ' + Cmd;
    ExpandEnvironmentStrings(@Cmd[1], Buf, SizeOf(Buf));
  FillChar(SA, SizeOf(SA), 0);
    SA.nLength := SizeOf(SA);
    SA.bInheritHandle := True;
    Hnd := CreateFile(PChar(TmpFn),
      GENERIC_READ or GENERIC_WRITE,
      0, @SA, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if Hnd = INVALID_HANDLE_VALUE then Exit;
  FillChar(SI, SizeOf(SI), 0);
    SI.cb := SizeOf(SA);
    SI.dwFlags :=
      STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
    SI.hStdOutput := Hnd;
    SI.hStdError := Hnd;
    SI.wShowWindow := SW_HIDE;
  if CreateProcess(nil, Buf, nil, nil, True, 0,
    nil, nil, SI, PI) then
  begin
    WaitForSingleObject(PI.hProcess, INFINITE);
    CloseHandle(PI.hThread);
    CloseHandle(PI.hProcess);
    SetLength(Result, GetFileSize(Hnd, nil));
    SetFilePointer(Hnd, 0, nil, FILE_BEGIN);
    ReadFile(Hnd, Result[1], Length(Result), Tmp, nil);
  end;
  CloseHandle(Hnd);
  DeleteFile(PChar(TmpFn));
end;

1 komentarz