我想从另一个delphi程序编译一个Delphi程序,为此,我使用ShellExecuteEx,以便该程序等待编译完成。
这工作正常,但我希望将.cmd输出放在.txt文件中,这不能正常工作。

    StartAndWait('cmd', '/c  c:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild xyz.dproj /t:Build /p:Config=release >> log.txt');


StartAndWait使用ShellExecuteEx启动该函数,并等待程序完成,

IF ShellExecuteEx(@SEInfo) THEN
BEGIN
  REPEAT
    Application.ProcessMessages;
    // Damit die Prozessorauslastung sinkt :-)
    Sleep(100);
    GetExitCodeProcess(SEInfo.hProcess, ExitCode);
  UNTIL (ExitCode <> STILL_ACTIVE) OR Application.Terminated;
  Result := True;
END;


谢谢!

最佳答案

我个人认为,通过调用CreateProcess可以更轻松地完成此操作。您需要创建一个文件句柄,并将其传递给CreateProcess用作标准输出。您需要注意一些细节,主要涉及句柄继承。您可以使用此功能完成所有操作:

procedure ExecuteCommandAndAppendToFile(
  const Executable: string;
  const Arguments: string;
  const WorkingDir: string;
  const OutputFile: string
);
const
  sa: TSecurityAttributes = (nLength: SizeOf(sa); bInheritHandle: True);
var
  hstdout: THandle;
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  cmd: string;
begin
  hstdout := CreateFile(PChar(OutputFile), GENERIC_WRITE, 0, @sa, OPEN_ALWAYS,
    FILE_ATTRIBUTE_NORMAL, 0);
  Win32Check(hstdout<>INVALID_HANDLE_VALUE);
  try
    //move to end of file since we wish to append
    SetFilePointer(hstdout, 0, nil, FILE_END);

    ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
    StartupInfo.cb := SizeOf(StartupInfo);
    StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
    StartupInfo.wShowWindow := SW_HIDE;
    StartupInfo.hStdOutput := hstdout;
    StartupInfo.hStdError := hstdout;

    cmd := Executable + ' ' + Arguments;
    UniqueString(cmd);//not needed but let's be explicit
    if not CreateProcess(nil, PChar(cmd), nil, nil, True,
      CREATE_NO_WINDOW or NORMAL_PRIORITY_CLASS, nil, PChar(WorkingDir),
      StartupInfo, ProcessInfo) then
    begin
      RaiseLastOSError;
    end;
    try
      WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    finally
      CloseHandle(ProcessInfo.hProcess);
      CloseHandle(ProcessInfo.hThread);
    end;
  finally
    CloseHandle(hstdout);
  end;
end;


这使用WaitForSingleObject等待完成。那将阻塞运行该代码的线程。如果您有不想阻止的GUI,则可以将此代码移到另一个线程中。或者,您可以使用MsgWaitForMultipleObjects。或者,如果需要的话,也可以使用基于Sleep的循环(我不太关心Sleep,但这是您的选择)。

因此,您可能希望对此做些微调,但此处提供了所有基础知识。

10-06 14:22