我正在尝试启动具有提升状态的外部应用程序,并等到它退出后再继续:
var
FProcess: THandle;
ExecInfo: TShellExecuteInfo;
begin
FillChar(ExecInfo, SizeOf(ExecInfo), 0);
with ExecInfo do
begin
cbSize := SizeOf(ExecInfo);
fMask := 0;
Wnd := AWindow;
lpVerb := 'runas';
lpFile := PChar(APath);
lpParameters := PChar(AParams);
lpDirectory := PChar(AWorkDir);
nShow := SW_NORMAL;
end;
Result := ShellExecuteEx(@ExecInfo);
if Wait then
begin
while WaitForSingleObject(ExecInfo.hProcess, INFINITE) <> WAIT_TIMEOUT do
Application.ProcessMessages;
end;
这启动了,但它一直在等待。即使在被调用的程序退出之后,调用程序也永远不会继续调用WaitForSingleObject。
我尝试过WAIT_OBJECT_0而不是WAIT_TIMEOUT,但我遇到了同样的问题。我在这里做错了什么?
答案 0 :(得分:11)
代码是什么
while WaitForSingleObject(ExecInfo.hProcess, INFINITE) <> WAIT_TIMEOUT do
Application.ProcessMessages;
该怎么办?这是一个无限循环。
仅使用
WaitForSingleObject(ExecInfo.hProcess, INFINITE);
代替。是的,你需要
fMask:= SEE_MASK_NOCLOSEPROCESS;
获取进程句柄。
答案 1 :(得分:4)
您的代码已损坏。您没有将SEE_MASK_NOCLOSEPROCESS
标记传递给ShellExecuteEx()
,因此它不会向您返回有效的流程句柄,并且您的循环忽略了WaitForSingleObject()
因此而告诉您的错误,因此你最终会陷入无休止的循环中。
请改为尝试:
var
ExecInfo: TShellExecuteInfo;
begin
ZeroMemory(@ExecInfo, SizeOf(ExecInfo));
with ExecInfo do
begin
cbSize := SizeOf(ExecInfo);
fMask := SEE_MASK_NOCLOSEPROCESS;
Wnd := AWindow;
lpVerb := 'runas';
lpFile := PChar(APath);
lpParameters := PChar(AParams);
lpDirectory := PChar(AWorkDir);
nShow := SW_NORMAL;
end;
Result := ShellExecuteEx(@ExecInfo);
if Result and Wait then
begin
if ExecInfo.hProcess <> 0 then // no handle if the process was activated by DDE
begin
repeat
if MsgWaitForMultipleObjects(1, ExecInfo.hProcess, FALSE, INFINITE, QS_ALLINPUT) = (WAIT_OBJECT_0+1) then
Application.ProcessMessages
else
Break;
until False;
CloseHandle(ExecInfo.hProcess);
end;
end;
end;
答案 2 :(得分:2)
如果您阅读description of ShellExecuteEx in MSDN,您会看到:
hProcess
Type: HANDLE
新启动的应用程序的句柄。此成员已开启 除非fMask,否则返回并始终为NULL 设置为SEE_MASK_NOCLOSEPROCESS。 即使fMask设置为 SEE_MASK_NOCLOSEPROCESS,hProcess将 如果没有启动进程,则为NULL。
即。你根本没有有效的句柄。您需要如上所述设置fMask。