Registriert seit: 9. Jul 2004
Ort: Aken (Anhalt-Bitterfeld)
1.335 Beiträge
Delphi XE5 Professional
|
Re: CreateProcess + XCOPY + Pipes = HILFE!!!
26. Aug 2007, 14:50
Zitat von FritzAT:
zu Garfiel:
danke für den link, aber der führt ins nirwana...
hast du einen aktuellen?
Bei mir funktioniert er.
Die fragliche Procedure:
Delphi-Quellcode:
procedure RunConsoleApp(const CommandLine: String; AStrings: TStrings);
type
TCharBuffer = array[0..MaxInt - 1] of Char;
const
MaxBufSize = 1024;
var
I: Longword;
SI: TStartupInfo;
PI: TProcessInformation;
SA: PSecurityAttributes;
SD: PSECURITY_DESCRIPTOR;
NewStdIn: THandle;
NewStdOut: THandle;
ReadStdOut: THandle;
WriteStdIn: THandle;
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;
end; {end VER_PLATFORM_WIN32_NT}
else
SA.lpSecurityDescriptor := nil;
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(SI);
SI.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
SI.wShowWindow := SW_SHOWNORMAL;
SI.hStdOutput := NewStdOut;
SI.hStdError := NewStdOut;
SI.hStdInput := NewStdIn;
if not CreateProcess(nil, PChar(CommandLine), nil, nil, True,
CREATE_NEW_CONSOLE, nil, nil, SI, PI) then
begin
CloseHandle(NewStdIn);
CloseHandle(NewStdOut);
CloseHandle(ReadStdOut);
CloseHandle(WriteStdIn);
RaiseLastWin32Error;
end; {end if}
Last := '';
BufferSize := MaxBufSize;
Buffer := AllocMem(BufferSize);
try
repeat
Win32Check(GetExitCodeProcess(PI.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; {end if}
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);
AStrings.Add(Str);
Str := '';
end; {end #10}
#13:
begin
inc(I);
if (I < Bread) and (Buffer^[I] = #10) then
inc(I);
AStrings.Add(Str);
Str := '';
end; {end #13}
else
begin
Str := Str + Buffer^[I];
inc(I);
end; {end else}
end; {end case}
end; {end while}
Last := Str;
end; {end if}
Sleep(1);
Application.ProcessMessages;
until (ExitCode <> STILL_ACTIVE);
if Last <> '' then
AStrings.Add(Last);
finally
FreeMem(Buffer);
end; {end try/finally}
CloseHandle(PI.hThread);
CloseHandle(PI.hProcess);
CloseHandle(NewStdIn);
CloseHandle(NewStdOut);
CloseHandle(ReadStdOut);
CloseHandle(WriteStdIn);
end; {end procedure}
Ich habe beispielsweise 'AStrings: TStrings' in 'Memo: TMemo' und 'AStrings.Add(Str);' in 'Memo.Lines.Add(Str);' geändert. Eventuell muss beim Memo wegen der Umlaute das Charset vom Standard Ansi_CharSet auf OEM_CharSet geändert werden.
Zitat von FritzAT:
Mein gedanke...
vielleicht funktioniert es nicht weil xcopy kein 'interner befehl' wie zb. dir, copy,...
usw. ist, den die 'echten internen befehle' funktionieren ALLE optimal.
Könnte es nicht sein das XCOPY anders 'gestarted' werden muß um die ausgabe zu erhalten?
Dein Befehl hat bei mir vorhin funktioniert.
__
Nachtrag:
War wohl gerade zu lange abgelenkt!?
Zitat von FritzAT:
Die procedure TForm1.RunConsoleApp(const CommandLine: String; AStrings: TStrings);
von OLLI hat GOTTSEIDANK mit XCOPY /? funktioniert(nochmals danke)
Von OLLI???
Gruss Garfield
Ubuntu 22.04: Laz2.2.2/FPC3.2.2 - VirtBox6.1+W10: D7PE, DXE5Prof
|