如何redirect standard input/output到我的console app |
尚未結案
|
little_spoon
一般會員 ![]() ![]() 發表:1 回覆:1 積分:0 註冊:2004-06-30 發送簡訊給我 |
我想寫一支程式能create一個新的process來執行指定的執行檔,
其中這個新的process會把standard input/output以pipe的方式送回
給parent process,目前若只將執行結果傳回是沒有問題的,但是我
希望它能夠具有interactive的能力,如child process執行telnet.exe,
而parent process可以透過pipe的read,write與child process互動。 我目前的做法是create兩個thread,一個負責read,一個負責write,但
結果似乎不如我的預期,不知是否有人看過類似的範例或者可以給我一
些建議 ------------------------------------------------------------------
以下是寫一半的code
------------------------------------------------------------------
unit Unit1; interface uses
SysUtils, windows, Dialogs; Const
Buff_Size = 1024;
var
NewStdIN, Write_StdIN, Read_StdOUT, NewStdOUT: THandle; procedure run(cmd: String); implementation function Read():Longint; stdcall;
var
WriteBuff: array [0..Buff_Size-1] of Char;
BytesWrite: DWORD;
begin
while (true) do
begin
FillChar(WriteBuff, SizeOf(WriteBuff), 0);
ReadFile(GetStdHandle(STD_INPUT_HANDLE), WriteBuff, Buff_Size, BytesWrite, Nil);
sleep(10);
BytesWrite := StrLen(WriteBuff);
WriteFile(Write_StdIN, WriteBuff, Buff_Size, BytesWrite, Nil);
end;
end; function Write():Longint; stdcall;
var
ReadBuff: array [0..Buff_Size-1] of Char;
BytesRead, TotalBytesAvail: DWORD;
begin
while (true) do
begin
PeekNamedPipe(Read_StdOUT,
@ReadBuff,
Buff_Size,
@BytesRead,
@TotalBytesAvail,
Nil); if (BytesRead <> 0) then
begin
FillChar(ReadBuff, SizeOf(ReadBuff), 0);
if (TotalBytesAvail > Buff_Size) then
begin
while (BytesRead >= Buff_Size) do
begin
ReadFile(Read_StdOUT, ReadBuff, Buff_Size, BytesRead, Nil);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), ReadBuff, Buff_Size, BytesRead, Nil);
FillChar(ReadBuff, SizeOf(ReadBuff), 0);
sleep(10);
end;
end
else
begin
ReadFile(Read_StdOUT, ReadBuff, Buff_Size, BytesRead, Nil);
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), ReadBuff, Buff_Size, BytesRead, Nil); end;
end;
end;
end; procedure run(cmd: String);
var
ProcessInfo: TProcessInformation;
SecurityAttr: TSecurityAttributes;
StartupInfo: TStartupInfo;
ExitCode: Cardinal;
ThreadID_W, ThreadID_R: DWORD;
begin //Init ProcessInfo
FillChar(ProcessInfo, SizeOf(TProcessInformation), 0); //Init SecurityAttr
FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
SecurityAttr.nLength := SizeOf(SecurityAttr);
SecurityAttr.bInheritHandle := true;
SecurityAttr.lpSecurityDescriptor := nil; //Create Pipes
if not CreatePipe(NewStdIN, Write_StdIN, @SecurityAttr, 0) then
begin
ShowMessage('Create Pipe Error => 1 !!');
GetLastError();
exit;
end;
if not CreatePipe(Read_StdOUT, NewStdOUT, @SecurityAttr, 0) then
begin
ShowMessage('Create Pipe Error => 2 !!');
CloseHandle(NewStdIN);
CloseHandle(Write_StdIN);
exit;
end; //Init StartupInfo
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
GetStartupInfo(StartupInfo);
StartupInfo.cb:=SizeOf(StartupInfo);
StartupInfo.hStdInput := NewStdIN;
StartupInfo.hStdOutput := NewStdOut;
StartupInfo.hStdError := NewStdOut;
StartupInfo.wShowWindow := SW_HIDE;
StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES; //CreateProcess
if not CreateProcess(nil,
PChar(cmd),
nil,
nil,
true,
CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,
nil,
nil,
StartupInfo,
ProcessInfo) then
begin
ShowMessage('CreateProcess Error!!!');
CloseHandle(NewStdIN);
CloseHandle(NewStdOut);
CloseHandle(Write_StdIN);
CloseHandle(Read_StdOut);
exit;
end; CloseHandle(NewStdIN);
CloseHandle(NewStdOUT);
CreateThread(nil, 0, @Read, nil, 0, ThreadID_R);
CreateThread(nil, 0, @Write, nil, 0, ThreadID_W);
While (True) do
begin
GetExitCodeProcess(ProcessInfo.hProcess, ExitCode);
if (ExitCode <> STILL_ACTIVE) then break;
end;
CloseHandle(Write_StdIN);
CloseHandle(Read_StdOut);
end; end.
|
little_spoon
一般會員 ![]() ![]() 發表:1 回覆:1 積分:0 註冊:2004-06-30 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |