【发布时间】:2014-11-01 15:30:24
【问题描述】:
我需要执行一个 'DOS' 程序(控制台应用程序)并动态检索其输出(能够随时结束 DOS 程序也很好,因为 DOS 程序可能会运行数小时)。
我有这个功能,但有时(很少)会死机。 我需要一个新功能或修复以下功能。
procedure ExecuteAndGetOutDyn(CONST ACommand, AParameters: String; AMemo: TMemo);
CONST
CReadBuffer = 128*KB; //original was 2400bytes
VAR
SecurityAttrib: TSecurityAttributes;
hRead: THandle;
hWrite: THandle;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
pBuffer: array[0..CReadBuffer] of AnsiChar;
dRead: DWord;
dRunning: DWord;
WasOK: Boolean;
begin
SecurityAttrib.nLength := SizeOf(TSecurityAttributes);
SecurityAttrib.bInheritHandle := True;
SecurityAttrib.lpSecurityDescriptor := nil;
if CreatePipe(hRead, hWrite, @SecurityAttrib, 0) then
begin
FillChar(StartupInfo, SizeOf(TStartupInfo), #0);
StartupInfo.cb := SizeOf(TStartupInfo);
StartupInfo.hStdInput := hRead;
StartupInfo.hStdOutput := hWrite;
StartupInfo.hStdError := hWrite;
StartupInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow:= SW_HIDE;
if CreateProcess(NIL, PChar(ACommand + ' ' + AParameters), @SecurityAttrib, @SecurityAttrib, True, NORMAL_PRIORITY_CLASS, NIL, NIL, StartupInfo, ProcessInfo) then
begin
REPEAT
dRunning:= WaitForSingleObject(ProcessInfo.hProcess, 100);
Application.ProcessMessages;
REPEAT
dRead := 0;
WasOK := Windows.ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, NIL);
if NOT WasOK then mesajerror('Cannot read console output.');
pBuffer[dRead] := #0;
OemToAnsi(pBuffer, (pBuffer));
AMemo.Lines.Add(String(pBuffer));
UNTIL (dRead < CReadBuffer) OR NOT WasOK;
UNTIL (dRunning <> WAIT_TIMEOUT) { OR Abort};
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
end;
CloseHandle(hRead);
CloseHandle(hWrite);
end;
end;
最大的问题是程序冻结没有特定的条件。我只是调用 ExecuteAndGetOutDyn,有时它会在“DOS”程序完成后冻结。我一发现就会发布出现冻结的条件。
【问题讨论】:
-
您的代码看起来基本正确。我就是这样做的。您的错误检查有点不稳定。
WaitForSingleObject可能会失败,在这种情况下,您可能不应该再阅读了。您不检查ReadFile的返回值,这似乎很不谨慎。请注意,管道全错了。程序的标准输出通过管道传送到它的输入中。你永远不想要那个。通常你会有两个管道。管道 1 是从您的流程到孩子输入的通道。管道 2 是从子输出返回到您的进程的通道。 -
我不愿意在没有 MCVE 的情况下尝试回答
-
还有最后一条评论。您没有执行 DOS 程序。这些是针对控制台子系统(也称为控制台应用程序)的 Windows 可执行文件。
-
你的调试告诉你什么?代码在哪里冻结?
-
添加一些诊断。输出调试字符串等
标签: delphi