Use ShellExecuteEx
, en lugar de ShellExecute
. Esta función proporcionará un identificador para el proceso creado, que puede usar para llamar al WaitForSingleObject
en ese identificador para bloquear hasta que el proceso finalice. Finalmente, solo llame al CloseHandle
en el identificador del proceso para cerrarlo.
Código de la muestra (la mayor parte de la comprobación de errores se omite para mayor claridad y brevedad):
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);
}
Especificación del verbo "runas" para el lpVerb
es lo que causa el UAC para elevar la aplicación que está a punto de ser lanzado. Esto es equivalente a establecer el nivel de permisos en el manifiesto de la aplicación para "requireAdministrator". Se requerirá elevación de UAC tanto para un administrador como para un usuario limitado.
Pero vale la pena señalar que a menos que sea absolutamente necesario, debe preferir la forma "estándar" de agregar un manifiesto a la aplicación que desea iniciar que especifique su nivel de ejecución requerido. Si sigue esta ruta, simplemente pasará "abrir" como lpVerb
. Un manifiesto de muestra se muestra a continuación:
<?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>
Por último, asegúrese de que cualquier elemento que en su aplicación provoca la ejecución del proceso que requiere elevación de UAC es marked accordingly. Es su trabajo modelar esto en la interfaz de usuario; Windows no lo maneja por ti.Esto se hace mostrando el icono de escudo en el punto de entrada; por ejemplo:

Esto se ve bien y es muy completo, gracias! Mi hijo exe ya está marcado como "requireAdministrator" en su manifiesto; lo siento, debería haber sido claro al respecto. – KenG
@KenG: De nada; Me alegra que esto funcione para ti. Originalmente asumí que tenías el manifiesto y solo intentabas ejecutar y esperar, pero luego me di cuenta de que tu pregunta en realidad no decía eso, así que volví y agregué algunos detalles más. De esta manera, sospecho que mi respuesta también será útil para otros en el futuro. –
Si la aplicación generada tiene un manifiesto de UAC asociado, entonces puede usar 'CreateProcess()', no necesita usar 'ShellExecutEx()'. 'CreateProcess()' realiza el aviso y la elevación de UAC necesarios si el manifiesto de la aplicación dice que lo haga. –