我有用Delphi XE2编写的VCL应用程序,需要执行命令行程序(也用Delphi XE2编写)并获取它的文本输出。我目前正在使用以下代码,该代码基于此处的代码:Getting output from a shell/dos app into a Delphi app
function GetDosOutput(ACommandLine : string; AWorkingDirectory : string): string;
var
SecurityAttributes : TSecurityAttributes;
StartupInfo : TStartupInfo;
ProcessInformation: TProcessInformation;
StdOutPipeRead, StdOutPipeWrite: THandle;
WasOK: Boolean;
Buffer: array[0..255] of AnsiChar;
BytesRead: Cardinal;
Handle: Boolean;
begin
Result := '';
SecurityAttributes.nLength := SizeOf(TSecurityAttributes);
SecurityAttributes.bInheritHandle := True;
SecurityAttributes.lpSecurityDescriptor := nil;
CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SecurityAttributes, 0);
try
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
StartupInfo.cb := SizeOf(TStartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
StartupInfo.wShowWindow := SW_HIDE;
StartupInfo.hStdInput := StdOutPipeRead;
StartupInfo.hStdOutput := StdOutPipeWrite;
StartupInfo.hStdError := StdOutPipeWrite;
FillChar(ProcessInformation, SizeOf(ProcessInformation), 0);
Handle := CreateProcess(
nil,
PChar(ACommandLine),
nil,
nil,
True,
0,
nil,
PChar(AWorkingDirectory),
StartupInfo,
ProcessInformation
);
CloseHandle(StdOutPipeWrite);
if Handle then
try
repeat
WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
if BytesRead > 0 then
begin
Buffer[BytesRead] := #0;
Result := Result + Buffer;
end;
until not WasOK or (BytesRead = 0);
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
finally
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
end;
finally
CloseHandle(StdOutPipeRead);
end;
end;
这适用于大多数Windows版本。不幸的是,最近我们注意到它在Windows XP上不起作用。对WaitForSingleObject的调用根本不会返回。我尝试用较小的值(例如15000)替换第二个参数INFINITE,但这似乎没有任何区别。在任务管理器中,我可以看到,在调用GetDosOutput之后,命令行程序实际上正在运行。如果我结束VCL应用程序,命令行程序然后似乎成功完成其工作(由它输出我期望它的文件的事实证明)。我还注意到,如果从StartupInfo.dwFlags中删除STARTF_USESTDHANDLES,命令行程序将正常运行并且WaitForSingleObject会立即返回;但是我显然无法获得该程序返回的文本。
是否有人建议我如何在Windows XP上运行?
答案 0 :(得分:3)
freepascal中有一个非常有用的单元叫做“process”,就是这样,并且已经完成端口它到Delphi 的工作所以你可以捕获 Delphi 中的命令输出使用简单的一行:
RunCommand()
或者您可以通过自己创建一个TProcess对象(RunCommand只是包装)来捕获具有更多高级功能的命令输出。
项目在这里:
如何将命令的输出,即“dir”(列出目录内容,着名的MS DOS命令)捕获到字符串中,然后将其添加到备忘录中:
uses
dprocess;
// ...
var
output: ansistring;
begin
RunCommand('cmd', ['/c', 'dir'], output, [poNoConsole]);
memo1.Lines.Add(output);
end;