我個人認爲通過致電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
,但它是你的選擇)。
所以,你不妨調整一下這個,但基本都在這裏。
你能指定如何失敗。另外,如果沒有「睡眠」,寫下等待會更好。你需要'MsgWaitForMultipleObjects'。或者運行shell的懶惰方式執行並等待後臺線程退出。這樣你可以使用'WaitForSingleObject'而不是阻止UI。就個人而言,如果我是你,我會放棄'cmd',並放棄'>>'並使用帶管道的'CreateProcess'來讀取另一個進程的'stdout'。 –
它沒有真正失敗,.txt只是保持空白。 你有一個例子如何用管道讀取stdout? – user3239791
你喜歡這樣做,而不是寫入文件? –