我想从我的Delphi代码运行后台应用程序。打开的应用程序是基于DOS的EXE,它将内容输出到DOS窗口。该程序将无限期地打开,直到它从任务管理器关闭。我用来打开应用程序的当前代码是;
procedure CaptureConsoleOutput(const ACommand, AParameters: String; CallBack: TArg<PAnsiChar>);
const
CReadBuffer = 2400;
var
saSecurity: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
suiStartup: TStartupInfo;
piProcess: TProcessInformation;
pBuffer: array [0 .. CReadBuffer] of AnsiChar;
dBuffer: array [0 .. CReadBuffer] of AnsiChar;
dRead: DWord;
dRunning: DWord;
begin
saSecurity.nLength := SizeOf(TSecurityAttributes);
saSecurity.bInheritHandle := True;
saSecurity.lpSecurityDescriptor := nil;
if CreatePipe(hRead, hWrite, @saSecurity, 0) then
begin
FillChar(suiStartup, SizeOf(TStartupInfo), #0);
suiStartup.cb := SizeOf(TStartupInfo);
suiStartup.hStdInput := hRead;
suiStartup.hStdOutput := hWrite;
suiStartup.hStdError := hWrite;
suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
suiStartup.wShowWindow := SW_HIDE;
if CreateProcess(nil, pChar(ACommand + ' ' + AParameters), @saSecurity, @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) then
begin
repeat
dRunning := WaitForSingleObject(piProcess.hProcess, 100);
//Application.ProcessMessages();
repeat
dRead := 0;
ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
if(dRead > 0) then
begin
pBuffer[dRead] := #0;
//ShowMessage(pBuffer);
//OemToAnsi(pBuffer, pBuffer);
//Unicode support by Lars Fosdal
OemToCharA(pBuffer, dBuffer);
CallBack(dBuffer);
end;
until (dRead < CReadBuffer);
until (dRunning <> WAIT_TIMEOUT);
CloseHandle(piProcess.hProcess);
CloseHandle(piProcess.hThread);
end;
CloseHandle(hRead);
CloseHandle(hWrite);
end;
end;
这很好,但是因为程序没有“退出”并且永远保持打开状态,我的应用程序挂起,代码永远不会移动。
任何帮助将不胜感激
答案 0 :(得分:10)
如果您不需要对生成的进程执行任何操作,只需关闭CreateProcess()
返回的句柄并继续操作,该进程将继续运行。但是,由于您似乎需要从生成的进程的输出中连续读取,您只需将该逻辑移动到工作线程中,这样您的主代码就不会被阻止了。
答案 1 :(得分:0)
//你必须把你的conde放在一个线程中。例如:
//假设您要ping Google服务器。你必须在Delphi中的接口部分创建一个类似//下面的线程。您可以通过选择File-New - // Other-Thread Object来完成此操作,然后根据需要命名您的线程。
型 TPing = class(TThread) 私人的 {私人声明} 保护 程序执行;覆盖; 端;
//将CaptureConsoleOutput过程复制到Thread单元。
//在Execute过程中,调用CaptureConsoleOutput过程。 //就我而言,我只是直接在Memo组件中捕获输出。
//对我来说效果很好!
程序TPing.Execute; 开始 优先级:= tpLower; CaptureConsoleOutput('ping www.yahoo.com',' - t',Form1.Memo2); 端;