Załóżmy że w swoim programie uruchamiam jakiś inny program.
Kolejne instrukcje powinny być wykonane dopiero po zakończeniu działania tamtego programu. Jak zrobić by na czas uruchomienia tamtego programu wykonanie mojego było wstrzymane?
Załóżmy że w swoim programie uruchamiam jakiś inny program.
Kolejne instrukcje powinny być wykonane dopiero po zakończeniu działania tamtego programu. Jak zrobić by na czas uruchomienia tamtego programu wykonanie mojego było wstrzymane?
Musisz zdobyć uchwyt procesu (na to są różne sposoby w zależnosci czy tamten program jest uruchamiany z poziomu Twojego programu, czy też jest to już działająca aplikacja okienkowa czy nie itd.) a do czekania na jego zakończenie możesz wykorzystać funkcję WaitForSingleObject
+wątki
W moim przypadku będzie to konsolowy 7-zip którego zadaniem będzie wypakowanie archiwum.
Skąd w takim przypadku pobrać uchwyt?
Jeżeli Ty uruchamiasz aplikację to zerknij na:
http://www.swissdelphicenter.ch/torry/showcode.php?id=93
nie testowałem ale powinno działać . Proponuję rozwiązania oparte na ShellExecuteEx
Ja w swoim programie odpalam wiele innych procesów z poziomu wiersza poleceń i sprawdzam czy zakończyły swoje działanie za pomocą czegoś takiego:
procedure WaitFor(processHandle: THandle);
var
msg: TMsg;
ret: DWORD;
begin
repeat
ret := MsgWaitForMultipleObjects(1, processHandle, False, INFINITE, QS_PAINT or QS_SENDMESSAGE);
if ret = WAIT_FAILED then Exit;
if ret = (WAIT_OBJECT_0 + 1) then begin
while PeekMessage(msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE) do begin
DispatchMessage(msg);
end;
end;
until ret = WAIT_OBJECT_0;
end;
kAzek, dzięki za link.
Wykorzystałem taki kod
function ExecAndWait(FileName: string; Visibility: Integer): DWORD;
procedure WaitFor(processHandle: THandle);
var
Msg: TMsg;
ret: DWORD;
begin
repeat
ret := MsgWaitForMultipleObjects(1, { 1 handle to wait on }
processHandle, { the handle }
False, { wake on any event }
INFINITE, { wait without timeout }
QS_PAINT or { wake on paint messages }
QS_SENDMESSAGE { or messages from other threads }
);
if ret = WAIT_FAILED then Exit; { can do little here }
if ret = (WAIT_OBJECT_0 + 1) then
begin
{ Woke on a message, process paint messages only. Calling
PeekMessage gets messages send from other threads processed. }
while PeekMessage(Msg, 0, WM_PAINT, WM_PAINT, PM_REMOVE) do
DispatchMessage(Msg);
end;
until ret = WAIT_OBJECT_0;
end; { Waitfor }
var { V1 by Pat Ritchey, V2 by P.Below }
zAppName: array[0..512] of char;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin { WinExecAndWait32V2 }
StrPCopy(zAppName, FileName);
FillChar(StartupInfo, SizeOf(StartupInfo), #0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := Visibility;
if not CreateProcess(nil,
zAppName, { pointer to command line string }
nil, { pointer to process security attributes }
nil, { pointer to thread security attributes }
False, { handle inheritance flag }
CREATE_NEW_CONSOLE or { creation flags }
NORMAL_PRIORITY_CLASS,
nil, { pointer to new environment block }
nil, { pointer to current directory name }
StartupInfo, { pointer to STARTUPINFO }
ProcessInfo) { pointer to PROCESS_INF } then
Result := DWORD(-1) { failed, GetLastError has error code }
else
begin
Waitfor(ProcessInfo.hProcess);
GetExitCodeProcess(ProcessInfo.hProcess, Result);
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
end; { Else }
end; { WinExecAndWait32V2 }
Działa świetnie.