Registriert seit: 9. Jul 2004
Ort: Aken (Anhalt-Bitterfeld)
1.335 Beiträge
Delphi XE5 Professional
|
Re: kommandozeilenprogramm aufrufen
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
|