Registriert seit: 31. Jul 2004
Ort: Chemnitz
316 Beiträge
Delphi 7 Personal
|
Problem mit Pipes und Threads
30. Sep 2006, 17:59
Hi,
ich bastl'e nun schon seit Stunden an einem Program (Konsole), welches die Ausgabe eines fremden Programms zurückliefert, wenn man ihm ein Komando gibt.
Bsp: ich gebe dem "CMD" den Befehl "dir" -> es wird eine Liste angezeigt (mit Files/...)
ich habe einige Codes im Netz gefunden (nur OOP, ich will das aber in einer Konsole haben), aber es funzt bei mir nicht.
Hier der Quellcode:
Delphi-Quellcode:
program test;
{$APPTYPE CONSOLE}
uses
Windows, Messages, SysUtils, StdCtrls,
_system, _strings;
var
cmd: String;
buf: Array[1..5000] of CHAR;
bytesRead: DWORD;
isRunning: BOOL;
process: DWORD;
thread: DWORD;
threadID: DWORD;
inputPipeRead: DWORD;
inputPipeWrite: DWORD;
outputPipeRead: DWORD;
outputPipeWrite: DWORD;
procedure pipeThreadProc;
var
i: DWORD;
begin
while ReadFile(outputPipeRead, buf[1], 5000, bytesRead, nil) or isRunning do
//wird nur einmal ausgeführt, wenn outputPipeWrite, dann geht es, aber buf ist leer
begin
if bytesRead > 0 then
for i := 1 to bytesRead do
Write(buf[i]);
Sleep(500);
Write(#7)
end
end;
procedure writeToStdIn(const text: String);
var
pos: DWORD;
written: DWORD;
res: BOOL;
len: DWORD;
begin
if not (text = '') then
begin
pos := 1;
len := DWORD(_strLen(text) + 2);
repeat
written := 0;
res := WriteFile(inputPipeWrite, text[pos], len - pos + 1, written, nil);
pos := pos + written
until not (res) or (pos > len)
end
end;
var
startupInfo: TStartupInfo;//_STARTUPINFOA; //TStartupInfo;
processInfo: TProcessInformation;
securityAttr: TSECURITYATTRIBUTES;
securityDesc: TSecurityDescriptor;
i: DWORD;
begin
//Starten
FillChar(securityDesc, SizeOf(securityDesc), 0);
FillChar(ProcessInfo,SizeOf(TProcessInformation),0);
InitializeSecurityDescriptor(@securityDesc, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(@securityDesc, true, nil, false);
with securityAttr do
begin
nLength := SizeOf(securityAttr);
lpSecurityDescriptor := @securityDesc;
bInheritHandle := true
end;
process := 0;
if CreatePipe(inputPipeRead, inputPipeWrite, @securityAttr, 0) then //Input-Pipe
if CreatePipe(outputPipeRead, outputPipeWrite, @securityAttr, 0) then //Output-Pipe
begin
FillChar(startupInfo, SizeOf(startupInfo), 0);
FillChar(processInfo, SizeOf(processInfo), 0);
with startupInfo do
begin
cb := SizeOf(startupInfo);
hStdOutput := outputPipeWrite;
hStdInput := inputPipeRead;
hStdError := outputPipeWrite;
dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
wShowWindow := SW_HIDE
end;
if CreateProcess(nil, PCHAR('Project2.exe'), @securityAttr, nil, true, 0, nil, nil,
startupInfo, processInfo) then //statt "project2" könnte auch "cmd" stehen
begin
process := processInfo.hProcess;
isRunning := true;
thread := CreateThread(nil, 100, @pipeThreadProc, nil, 0, threadID);
isRunning := not (thread = 0)
end
else
begin
CloseHandle(inputPipeRead);
CloseHandle(inputPipeWrite);
CloseHandle(outputPipeRead);
CloseHandle(outputPipeWrite)
end
end
else
begin
CloseHandle(inputPipeRead);
CloseHandle(inputPipeWrite)
end;
//CMD lesen
cmd := '';
while not (cmd = '#exit') do
begin
ReadLn(cmd);
writeToStdIn(cmd)
end;
//Beenden
if not (process = 0) then
begin
isRunning := false;
TerminateThread(thread, 0);
CloseHandle(inputPipeRead);
CloseHandle(inputPipeWrite);
CloseHandle(outputPipeRead);
CloseHandle(outputPipeWrite);
TerminateProcess(process, 0); //CMD-Fenster schließen
CloseHandle(process);
process := 0
end;
ReadLn
end.
Was muss ich ändern, damit es geht?
Sebastian
|