我需要从Delphi XE2应用程序启动MS Window的OpenFiles.exe,以将当前打开的文件导出到文本文件。正常的cmd.exe语法类似于:

Openfiles.exe /query /s 127.0.0.1 /nh >c:\OpenFilesExport.txt


使用以下代码将返回成功的退出代码,但不会生成导出文件:

var
  exInfo: TShellExecuteInfo;
  exitcode: DWORD;
begin
  FillChar(exInfo, Sizeof(exInfo), 0);
  with exInfo do
  begin
    cbSize := Sizeof(exInfo);
    fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
    lpVerb := 'open';
    lpFile := Pchar('Openfiles.exe');
    lpParameters := PChar('/query /s 127.0.0.1 /nh >c:\OpenFilesOutput.txt');
    nShow := SW_SHOWNORMAL
  end;
  if ShellExecuteEx(@exInfo) then
  begin
    while GetExitCodeProcess(exInfo.hProcess, exitcode)
      and (exitcode = STILL_ACTIVE) do
      Application.ProcessMessages();

    CloseHandle(exInfo.hProcess);
  end
  else
    ShowMessage(SysErrorMessage(GetLastError));


我还尝试将cmd.exe语法放在bat文件中,然后从shellexecute启动它,它确实会生成该文件,但是没有内容。从资源管理器运行相同的bat文件会生成预期的文件。

如何从ShellExecute成功启动Openfiles.exe?

最佳答案

您的问题是重定向>,仅当您具有命令解释器时才有意义。而且在您的代码中您没有。您有两种选择:


调用ShellExecuteEx并传递命令解释器以完成工作。
使用CreateProcess执行其他进程,但是将一个句柄作为新进程的stdout句柄传递给文件。


对于命令解释器选项,您将具有以下命令行:

cmd /c Openfiles.exe /query /s 127.0.0.1 /nh >c:\OpenFilesExport.txt


代码可能像这样:

FillChar(exInfo, Sizeof(exInfo), 0);
with exInfo do
begin
  cbSize := Sizeof(exInfo);
  fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_DDEWAIT;
  lpFile := 'cmd.exe';
  lpParameters := '/c Openfiles.exe /query /s 127.0.0.1 /nh >c:\OpenFilesExport.txt';
  nShow := SW_SHOWNORMAL;
end;


对于CreateProcess选项,您需要使用对CreateFile的调用来创建文件,并将该句柄作为新进程的stdout传递。您需要确保文件句柄是可继承的。最后,您将需要等待该过程,以便关闭文件句柄。

关于您当前的代码,您的等待不是很愉快。这是一个繁忙的等待,不必要地消耗了CPU。您应该在进程句柄上使用阻塞等待。

关于delphi - 如何从Delphi XE2 ShellExecute启动OpenFiles.exe?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20020450/

10-12 15:16