Delphi:ShellExecuteEx到.txt文件

时间:2014-01-27 09:22:05

标签: delphi delphi-xe2

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

    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;

谢谢!

1 个答案:

答案 0 :(得分:4)

我个人认为通过拨打CreateProcess更容易。您需要创建一个文件句柄,并将其传递给CreateProcess以用作stdout。您需要注意一些细节,主要涉及句柄继承。您可以使用此功能完成所有操作:

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,但这是您的选择。)

所以,您可能希望调整一下这些,但基本知识都存在于此处。