Use ShellExecuteEx
, rather than ShellExecute
. This function will provide a handle for the created process, which you can use to call WaitForSingleObject
on that handle to block until that process terminates. Finally, just call CloseHandle
on the process handle to close it.
Sample code (most of the error checking is omitted for clarity and brevity):
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);
}
Specifying the "runas" verb for the lpVerb
is what causes UAC to elevate the application that's about to be launched. This is the equivalent of setting the permissions level in the application's manifest to "requireAdministrator". It will require UAC elevation for both an administrator and a limited user.
But it's worth noting that unless absolutely necessary, you should prefer the "standard" way of adding a manifest to the application you want to launch that specifies its required execution level. If you go this route, you will simply pass "open" as the lpVerb
. A sample manifest is shown below:
<?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>
Finally, make sure that whatever element in your application triggers execution of the process requiring UAC elevation is marked accordingly. It's your job to model this in the user interface; Windows doesn't handle it for you. This is done by displaying the shield icon on the entry point; for example:
