我有一个希望很快的问题:是否有可能延迟执行ShellExecute一点?
我有一个autoupdater应用程序。在下载所有必需的文件等之后,它会将当前文件重命名为* .OLD,将新文件重命名为之前的文件。很简单。但后来我需要删除那些.OLD文件。这个'清理'程序在MainForm.OnActivate上执行(检查它是否是第一个激活proc)。但这显然发生得太快(我从DeleteFile得到False)。这是程序:
procedure TUpdateForm.OKBtnClick(Sender: TObject);
const SHELL = 'ping 127.0.0.1 -n 2';
begin
ShellExecute(0,'open',pchar(SHELL+#13+Application.ExeName),nil,nil,SW_SHOWNORMAL);
Application.Terminate;
end;
此过程应该重新启动应用程序。我确定删除问题是由第二个应用程序的快速启动引起的,因为如果我自己重新启动它,给它一点时间,文件会被正常删除。
tl; dr 版本:我需要调用ShellExecute()等待一段时间(0.1秒左右),然后THEN执行命令。
注意 的
我尝试使用-ping命令尝试延迟它,但它没有用。
非常感谢您提前
修改:改写
我需要这个发生|| 第一个应用关闭;等待100毫秒;第二个应用程序打开 ||。我需要先调用ShellExecute,然后等待调用应用程序完全关闭,然后执行shell(即打开第二个应用程序)
答案 0 :(得分:5)
你正在做自动检查吗?
我遇到了同样的问题,这就是我绕过它的方式:
您使用参数“--delay”运行第二个应用程序或类似的东西。 第二个应用处理参数“--delay”并休眠100毫秒,然后继续正常运行。
答案 1 :(得分:3)
这个例程是我们游戏引擎中的一些utils代码。它可以运行可执行文件并可选择等待它退出。它将返回其退出代码:
function TSvUtils.FileExecute(ahWnd: Cardinal; const aFileName, aParams, aStartDir: string; aShowCmd: Integer; aWait: Boolean): Integer;
var
Info: TShellExecuteInfo;
ExitCode: DWORD;
begin
Result := -1;
FillChar(Info, SizeOf(Info), 0);
Info.cbSize := SizeOf(TShellExecuteInfo);
with Info do begin
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := ahWnd;
lpFile := PChar(aFileName);
lpParameters := PChar(aParams);
lpDirectory := PChar(aStartDir);
nShow := aShowCmd;
end;
if ShellExecuteEx(@Info) then
begin
if aWait then
begin
repeat
Sleep(1);
Application.ProcessMessages;
GetExitCodeProcess(Info.hProcess, ExitCode);
until (ExitCode <> STILL_ACTIVE) or Application.Terminated;
CloseHandle(Info.hProcess);
Result := ExitCode;
end;
end
end;
以下是一些可以检查进程是否存在的代码。所以...当前应用程序调用更新程序并终止。更新程序可以检查旧应用程序是否已终止并执行此操作(重命名,更新,删除等):
function TSvUtils.ProcessExists(const aExeFileName: string; aBringToForgound: Boolean=False): Boolean;
var
ContinueLoop: BOOL;
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
begin
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
Result := False;
while Integer(ContinueLoop) <> 0 do
begin
if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
UpperCase(aExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) =
UpperCase(aExeFileName))) then
begin
if aBringToForgound then
EnumWindows(@BringToForgroundEnumProcess, FProcessEntry32.th32ProcessID);
Result := True;
end;
ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;
答案 2 :(得分:2)
如果您可以使用CreateProcess
而不是ShellExecute
,则可以等待进程句柄。应用程序退出时会发出进程句柄信号。例如:
function ExecAndWait(APath: string; var VProcessResult: cardinal): boolean;
var
LWaitResult : integer;
LStartupInfo: TStartupInfo;
LProcessInfo: TProcessInformation;
begin
Result := False;
FillChar(LStartupInfo, SizeOf(TStartupInfo), 0);
with LStartupInfo do
begin
cb := SizeOf(TStartupInfo);
dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
wShowWindow := SW_SHOWDEFAULT;
end;
if CreateProcess(nil, PChar(APath), nil, nil,
False, NORMAL_PRIORITY_CLASS,
nil, nil, LStartupInfo, LProcessInfo) then
begin
repeat
LWaitResult := WaitForSingleObject(LProcessInfo.hProcess, 500);
// do something, like update a GUI or call Application.ProcessMessages
until LWaitResult <> WAIT_TIMEOUT;
result := LWaitResult = WAIT_OBJECT_0;
GetExitCodeProcess(LProcessInfo.hProcess, VProcessResult);
CloseHandle(LProcessInfo.hProcess);
CloseHandle(LProcessInfo.hThread);
end;
end;
ExecAndWait返回后,如果需要,你可以睡100ms。
N - [