Используйте 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 не справится с этим. Это делается путем отображения значка щита в точке входа; например: