Einzelnen Beitrag anzeigen

Benutzerbild von Garfield
Garfield

Registriert seit: 9. Jul 2004
Ort: Aken (Anhalt-Bitterfeld)
1.335 Beiträge
 
Delphi XE5 Professional
 
#3

Re: kommandozeilenprogramm aufrufen

  Alt 28. Nov 2005, 14:03
Ich weiß jetzt nicht, was Du alles von dem Aufruf verlangst, aber ich verwende den folgenden Code, welchen ich mal in einem anderen Forum gefunden und etwas angepasst habe:

Delphi-Quellcode:
var
  // Um Abbrechen zu können
  ProcessInfo : TProcessInformation;


function RunConsoleApp(const CommandLine : String; Datei : String): Boolean;
const
  IDLE_PRIORITY_CLASS = $40;
  BELOW_NORMAL_PRIORITY_CLASS = $4000;
  NORMAL_PRIORITY_CLASS = $20;
  ABOVE_NORMAL_PRIORITY_CLASS = $8000;
  HIGH_PRIORITY_CLASS = $80;
  REALTIME_PRIORITY_CLASS = $100;
type
  TCharBuffer = array[0..MaxInt - 1] of Char;
const
  MaxBufSize = 1024;
var
  ProPri : integer;
  I : Longword;
  NewStdIn : THandle;
  NewStdOut : THandle;
  ReadStdOut : THandle;
  WriteStdIn : THandle;
  StartupInfo : TStartupInfo;
// ProcessInfo : TProcessInformation;
  SA : PSecurityAttributes;
  SD : PSECURITY_DESCRIPTOR;
  Buffer : ^TCharBuffer;
  BufferSize : Cardinal;
  Last : WideString;
  Str : WideString;
  ExitCode : DWORD;
  Bread : DWORD;
  Avail : DWORD;
begin
  GetMem(SA, SizeOf(TSecurityAttributes));

  case Win32Platform of
    VER_PLATFORM_WIN32_NT:
      begin
        GetMem(SD, SizeOf(SECURITY_DESCRIPTOR));
        Win32Check(InitializeSecurityDescriptor(SD, SECURITY_DESCRIPTOR_REVISION));
        Win32Check(SetSecurityDescriptorDacl(SD, True, nil, False));
        SA.lpSecurityDescriptor := SD;

        case Haupt.CoProcess.ItemIndex of
          0: ProPri := IDLE_PRIORITY_CLASS;
          1: ProPri := BELOW_NORMAL_PRIORITY_CLASS;
          2: ProPri := NORMAL_PRIORITY_CLASS;
          3: ProPri := ABOVE_NORMAL_PRIORITY_CLASS;
          4: ProPri := HIGH_PRIORITY_CLASS;
        end;
      end; {end VER_PLATFORM_WIN32_NT}
    else begin
      SA.lpSecurityDescriptor := nil;

      case Haupt.CoProcess.ItemIndex of
        0: ProPri := IDLE_PRIORITY_CLASS;
        1: ProPri := NORMAL_PRIORITY_CLASS;
        2: ProPri := HIGH_PRIORITY_CLASS;
      end;
    end;
  end; {end case}

  SA.nLength := SizeOf(SECURITY_ATTRIBUTES);
  SA.bInheritHandle := True;

  Win32Check(CreatePipe(NewStdIn, WriteStdIn, SA, 0));

  if not CreatePipe(ReadStdOut, NewStdOut, SA, 0) then
  begin
    CloseHandle(NewStdIn);
    CloseHandle(WriteStdIn);
    RaiseLastWin32Error;
  end; {end if}

  GetStartupInfo(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := SW_HIDE; // SW_SHOWNORMAL;
  StartupInfo.hStdOutput := NewStdOut;
  StartupInfo.hStdError := NewStdOut;
  StartupInfo.hStdInput := NewStdIn;

  if not CreateProcess(
    nil,
    PChar(CommandLine),
    nil,
    nil,
    True,
    ProPri, // and CREATE_NEW_CONSOLE,
    nil,
    nil,
    StartupInfo,
    ProcessInfo)
  then begin
    CloseHandle(NewStdIn);
    CloseHandle(NewStdOut);
    CloseHandle(ReadStdOut);
    CloseHandle(WriteStdIn);
    RaiseLastWin32Error;
  end {end if}
  else begin
    Last := '';
    BufferSize := MaxBufSize;
    Buffer := AllocMem(BufferSize);

    try
      repeat
        Win32Check(GetExitCodeProcess(ProcessInfo.hProcess, ExitCode));
        PeekNamedPipe(ReadStdOut, Buffer, BufferSize, @Bread, @Avail, nil);

        if (Bread <> 0) then
        begin
          if (BufferSize < Avail) then
          begin
            BufferSize := Avail;
            ReallocMem(Buffer, BufferSize);
          end;
          FillChar(Buffer^, BufferSize, #0);
          ReadFile(ReadStdOut, Buffer^, BufferSize, Bread, nil);
          Str := Last;
          I := 0;

          while (I < Bread) do
          begin
            case Buffer^[I] of
              #0: inc(I);
              #10:
                begin
                  inc(I);
                  Add_Log(Str);
                  Str := '';
                end; {end #10}
              #13:
                begin
                  inc(I);
                  if (I < Bread) and (Buffer^[I] = #10)
                  then begin
                    inc(I);
                    Add_Log(Str);
                  end
                  else
                    Add_Log(Str);
                  Str := '';
                end; {end #13}
              else
                begin
                  Str := Str + Buffer^[I];
                  inc(I);
                end;
            end; {end case}
          end; {end while}
          Last := Str;
        end; {end if}
        Sleep(100);

        Application.ProcessMessages;

      until (ExitCode <> STILL_ACTIVE);

      if Last <> 'then Add_Log(Last);

    finally
      FreeMem(Buffer);

      CloseHandle(ProcessInfo.hThread);
      CloseHandle(ProcessInfo.hProcess);
      CloseHandle(NewStdIn);
      CloseHandle(NewStdOut);
      CloseHandle(ReadStdOut);
      CloseHandle(WriteStdIn);
    end; {end try/finally}
  end;

  case Exitcode of
    ...
  end;
end;


function RunConsoleApp_Beenden : Boolean;
begin
  try
    TerminateProcess (ProcessInfo.hProcess, 0);
    Result := True
  except
    Result := False;
  end;
end;
ProcessInfo ist nicht in der Procedure RunConsoleApp vereinbart, damit man den Vorgang über RunConsoleApp_Abbrechen abbrechen kann. Haupt.CoProcess ist eine Combobox, in welcher die Processpriorität eingestellt werden kann. Add_Log ist ein Procedure, um den Text, welcher von der Consolenanwendung zurückkommt, formatiert auszugeben. Abschließend kann man einen Errorcode auswerten, falls die Consolenanwendung einen zurückgibt.
Gruss Garfield
Ubuntu 22.04: Laz2.2.2/FPC3.2.2 - VirtBox6.1+W10: D7PE, DXE5Prof
  Mit Zitat antworten Zitat