2011-05-24 3 views

Respuesta

4

Como señaló Tamás, debe iniciar un nuevo proceso con derechos elevados. Busqué mucho en el pasado, pero no encontré ninguna manera de elevar los derechos del proceso actual.

Digamos que su aplicación principal es App1.exe y luego llama a un proceso secundario App2.exe que requiere derechos elevados.


A. Puede incrustar un manifiesto en su App2.exe pero la forma más simple es crear un archivo de manifiesto [un archivo de texto] llamado App2.exe.manifest con el siguiente contenido y ponerlo en el mismo directorio que App2.exe. Nota: !! Por extraño que parezca, si el nombre de su aplicación no es App2.exe sino App2_install.exe o App2_setup.exe (es decir, si el nombre de la aplicación contiene la "instalación" o "configuración") aparecerá un cuadro de diálogo UAC automáticamente en Windows Vista/Windows 7 y pedirá derechos elevados incluso si no hay un archivo manifiesto !! Esta es una muestra del archivo de manifiesto:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> 
<security> 
<requestedPrivileges> 
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> 
</requestedPrivileges> 
</security> 
</trustInfo> 
</assembly> 

B. Usted puede usar un código como el siguiente en APP1.EXE para lanzar el App2.exe

QString AppToExec = qApp->applicationDirPath() + "/App2.exe"; 
// Put any required parameters of App2.exe to AppParams string 
QString AppParams = ""; 
if (0 != genWin32ShellExecute(AppToExec, 
           "", // default verb: "open" or "exec" 
           AppParams, 
           false, // run hidden 
           true)) // wait to finish 
{ 
    // (...) handle error 
} 

. ..y, finalmente, este es el código de la función genWin32ShellExecute Win32() creé para poner en marcha un proceso o abrir un documento utilizando QT en un Win32 O/S:

Header:

#ifdef Q_OS_WIN // Implement genWin32ShellExecute() especially for UAC 
    #include "qt_windows.h" 
    #include "qwindowdefs_win.h" 
    #include <shellapi.h> 

int genWin32ShellExecute(QString AppFullPath, 
         QString Verb, 
         QString Params, 
         bool ShowAppWindow, 
         bool WaitToFinish); 
#endif 

CPP:

// Execute/Open the specified Application/Document with the given command 
// line Parameters 
// (if WaitToFinish == true, wait for the spawn process to finish) 
// 
// Verb parameter values: 
// ""   The degault verb for the associated AppFullPath 
// "edit"  Launches an editor and opens the document for editing. 
// "find"  Initiates a search starting from the specified directory. 
// "open"  Launches an application. If this file is not an executable file, its associated application is launched. 
// "print"  Prints the document file. 
// "properties" Displays the object's properties. 
// 
// Ret: 0 = success 
//  <0 = error 
#ifdef Q_OS_WIN 
int genWin32ShellExecute(QString AppFullPath, 
         QString Verb, 
         QString Params, 
         bool ShowAppWindow, 
         bool WaitToFinish) 
{ 
    int Result = 0; 

    // Setup the required structure 
    SHELLEXECUTEINFO ShExecInfo; 
    memset(&ShExecInfo, 0, sizeof(SHELLEXECUTEINFO)); 
    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); 
    ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; 
    ShExecInfo.hwnd = NULL; 
    ShExecInfo.lpVerb = NULL; 
    if (Verb.length() > 0) 
     ShExecInfo.lpVerb = reinterpret_cast<const WCHAR *>(Verb.utf16()); 
    ShExecInfo.lpFile = NULL; 
    if (AppFullPath.length() > 0) 
     ShExecInfo.lpFile = reinterpret_cast<const WCHAR *>(AppFullPath.utf16()); 
    ShExecInfo.lpParameters = NULL; 
    if (Params.length() > 0) 
     ShExecInfo.lpParameters = reinterpret_cast<const WCHAR *>(Params.utf16()); 
    ShExecInfo.lpDirectory = NULL; 
    ShExecInfo.nShow = (ShowAppWindow ? SW_SHOW : SW_HIDE); 
    ShExecInfo.hInstApp = NULL; 

    // Spawn the process 
    if (ShellExecuteEx(&ShExecInfo) == FALSE) 
    { 
     Result = -1; // Failed to execute process 
    } else if (WaitToFinish) 
    { 
     WaitForSingleObject(ShExecInfo.hProcess, INFINITE); 
    } 

    return Result; 
} 
#endif 
+0

De hecho, fui yo quien lo señaló después de mi investigación: P. Gracias por la respuesta detallada. Si el nombre del ejecutable también contiene la cadena "actualizar" también activará el UAC. –

+0

Edité mi respuesta y puse su nombre en los créditos :-) Debo agradecerle por preguntar y darme el motivo para publicar este fragmento de código. Recuerdo que he gastado al menos 1-2 días cuando necesitaba este código porque no había una pregunta correspondiente en SO. –

+0

Gracias que no era necesario :). Realmente aprecio que se haya tomado el tiempo de escribir esta respuesta detallada, a pesar de que la pregunta ya tenía una respuesta aceptada. –

2

En pocas palabras: crea dos archivos ejecutables para Windows. El ejecutable regular y un archivo exe de trabajador que usa para realizar operaciones "elevadas" (pasando opciones de línea de comando).

Al segundo archivo EXE se agrega un archivo de manifiesto de aplicación con un nodo <requestExecutionLevel level="requireAdministrator"/>.

Al iniciar la aplicación de trabajador, asegúrese de usar la función QT que envuelve ShellExecute, NO CreateProcess ya que CreateProcess simplemente no inicia aplicaciones requireAdministrator, mientras que ShellExecute (al ser una función de shell) puede realizar la solicitud de elevación de UAC.

También es posible hacerlo con los controles ActiveX, pero como se dirige a Qt parece menos apropiado.

2

También puede iniciar un objeto COM en modo elevado. Consulte esto MSDN article para obtener más información.

Cuestiones relacionadas