使用ShellExecuteEx
,而不是ShellExecute
。此函数将为创建的进程提供一个句柄,您可以使用该句柄调用WaitForSingleObject
该句柄以阻塞直到该进程终止。最后,只需调用CloseHandle
进程句柄即可将其关闭。
示例代码(为了清晰和简洁省略了大部分错误检查):
SHELLEXECUTEINFO shExInfo = {0};
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExInfo.hwnd = 0;
shExInfo.lpVerb = _T("runas"); // Operation to perform
shExInfo.lpFile = _T("C:\\MyApp.exe"); // Application to start
shExInfo.lpParameters = ""; // Additional parameters
shExInfo.lpDirectory = 0;
shExInfo.nShow = SW_SHOW;
shExInfo.hInstApp = 0;
if (ShellExecuteEx(&shExInfo))
{
WaitForSingleObject(shExInfo.hProcess, INFINITE);
CloseHandle(shExInfo.hProcess);
}
为 指定“runas”动词lpVerb
是导致 UAC 提升即将启动的应用程序的原因。这相当于将应用程序清单中的权限级别设置为“requireAdministrator”。管理员和受限用户都需要 UAC 提升。
但值得注意的是,除非绝对必要,否则您应该更喜欢将清单添加到要启动的应用程序的“标准”方式,以指定其所需的执行级别。如果您走这条路线,您只需将“open”作为lpVerb
. 示例清单如下所示:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel
level="requireAdministrator"
uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
最后,确保应用程序中触发执行需要 UAC 提升的流程的任何元素都被相应地标记。在用户界面中对此进行建模是您的工作;Windows 不会为您处理它。这是通过在入口点上显示盾牌图标来完成的;例如: