做了个小小的修改, 主要是解决了NT/2000下的问题, 有2000/NT的帮忙试一下...<br><br>unit Unit1;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br> StdCtrls;<br><br>const<br> WM_INPUT = WM_USER + 1;<br> WM_OUTPUT = WM_USER + 2;<br> <br>type<br> TExecThread = class(TThread)<br> private<br> FWnd : HWND;<br> FCmdLine : String;<br><br> FInRead : THandle;<br> FInWrite : THandle;<br> FOutRead : THandle;<br> FOutWrite: THandle;<br><br> function isNT: Boolean;<br><br> protected<br> procedure Execute; override;<br> public<br> constructor Create(aWnd: HWND; const aCmdLine: String);<br> destructor Destroy; override;<br> end;<br><br>type<br> TForm1 = class(TForm)<br> Memo1: TMemo;<br> Button1: TButton;<br> Memo2: TMemo;<br> procedure Button1Click(Sender: TObject);<br> procedure Memo2KeyPress(Sender: TObject; var Key: Char);<br> private<br> { Private declarations }<br> FExec : TExecThread;<br> procedure WMOUTPUT(var Msg: TMessage); message WM_OUTPUT;<br> public<br> { Public declarations }<br> end;<br><br>var<br> Form1: TForm1;<br><br>implementation<br><br>{$R *.DFM}<br><br>constructor TExecThread.Create(aWnd: HWND; const aCmdLine: String);<br>var<br> SA : TSecurityAttributes;<br> SD : TSecurityDescriptor;<br>begin<br> inherited Create(False);<br> FreeOnTerminate := True;<br><br> FillChar(SA, SizeOf(TSecurityAttributes), 0);<br> SA.nLength := SizeOf(TSecurityAttributes);<br> SA.bInheritHandle := True;<br><br> if isNT then<br> begin<br> InitializeSecurityDescriptor(@SD, SECURITY_DESCRIPTOR_REVISION);<br> SetSecurityDescriptorDacl(@SD, True, nil, False);<br> SA.lpSecurityDescriptor := @SD;<br> end;<br><br> CreatePipe(FInRead, FInWrite, @SA, 0);<br> CreatePipe(FOutRead, FOutWrite, @SA, 0);<br><br> FCmdLine := aCmdLine;<br> FWnd := aWnd;<br>end;<br><br>destructor TExecThread.Destroy;<br>begin<br> CloseHandle(FInWrite);<br> CloseHandle(FInRead);<br> CloseHandle(FOutWrite);<br> CloseHandle(FOutRead);<br><br> inherited Destroy;<br>end;<br><br>function TExecThread.isNT: Boolean;<br>var<br> V : TOSVersionInfo;<br>begin<br> V.dwOSVersionInfoSize := SizeOf(V);<br> GetVersionEx(V);<br> Result := (V.dwPlatformId = VER_PLATFORM_WIN32_NT);<br>end;<br><br>procedure TExecThread.Execute;<br>var<br> SI : TStartupInfo;<br> PI : TProcessInformation;<br> EC : Cardinal;<br> Msg: TMsg;<br> C : Char;<br> N : Cardinal;<br> T : Cardinal;<br> I : Cardinal;<br> Buf: array[0..1023] of Byte;<br><br>begin<br> GetStartupInfo(SI);<br> SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;<br> SI.hStdInput := FInRead;<br> SI.hStdOutput := FOutWrite;<br> SI.hStdError := FOutWrite;<br> SI.wShowWindow := SW_HIDE;<br><br> if CreateProcess(nil, PChar(FCmdLine), nil, nil, True, 0, nil, nil, SI, PI) then<br> begin<br> repeat<br> Sleep(10);<br> PeekNamedPipe(FOutRead, @Buf, SizeOf(Buf), @N, @T, nil);<br> for I := 1 to T do<br> begin<br> ReadFile(FOutRead, C, SizeOf(C), N, nil);<br> if N <> 0 then PostMessage(FWnd, WM_OUTPUT, Ord(C), 0);<br> end;<br><br> while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do<br> begin<br> TranslateMessage(Msg);<br> DispatchMessage(Msg);<br> if WM_INPUT = Msg.message then<br> begin<br> C := Chr(Msg.wParam);<br> WriteFile(FInWrite, C, SizeOf(C), N, nil);<br> end;<br> end;<br><br> GetExitCodeProcess(PI.hProcess, EC);<br> until EC <> STILL_ACTIVE;<br><br> CloseHandle(PI.hThread);<br> CloseHandle(PI.hProcess);<br> end;<br>end;<br><br>procedure TForm1.WMOUTPUT(var Msg: TMessage);<br>begin<br> Memo1.Text := Memo1.Text + Chr(Msg.WParam);<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br> FExec := TExecThread.Create(Handle, 'C:/COMMAND.COM');<br>end;<br><br>procedure TForm1.Memo2KeyPress(Sender: TObject; var Key: Char);<br>begin<br> PostThreadMessage(FExec.ThreadID, WM_INPUT, Ord(Key), 0);<br>end;<br><br>end.<br>