How can I ask the user for elevated permissions at runtime?

后端 未结 4 1152
小蘑菇
小蘑菇 2020-12-29 15:01

Some applications, started with a regular user will ask for elevated permissions when necessary (e.g. a file manager needs to write such folder), and then carry on with the

相关标签:
4条回答
  • 2020-12-29 15:22

    In a nutshell: Create two executable files for windows. The regular executable, and a worker exe file that you use to perform "elevated" operations (by passing command line options).

    To the second EXE file you add an application manifest file with a <requestExecutionLevel level="requireAdministrator"/> node.

    When launching the worker app, make sure to use the QT function that wraps ShellExecute, NOT CreateProcess as CreateProcess simply fails to launch requireAdministrator apps, whereas ShellExecute (Being a shell function) can perform the UAC elevation prompt.

    It is also possible to do this with ActiveX controls, but as you are targeting Qt that seems less appropriate.

    0 讨论(0)
  • 2020-12-29 15:30

    You can also launch a COM object in an elevated mode. See this MSDN article for more information.

    0 讨论(0)
  • 2020-12-29 15:34

    As Tamás pointed out you need to launch a new process with elevated rights. I searched a lot in the past but I did not find any way to elevate the rights of the current process.

    Lets say your primary app is App1.exe and then you call a secondary process App2.exe which requires elevated rights.


    A. You can embed a manifest in your App2.exe but the simpler way is to create a manifest file [a text file] named App2.exe.manifest with the following contents and put it in the same directory as App2.exe. Note: !! Strangely enough, if the name of your application is not App2.exe but App2_install.exe or App2_setup.exe (i.e. if the application name contains the "install" or "setup") an UAC Dialog will appear automatically in Windows Vista / Windows 7 and will ask for elevated rights even there is no manifest file !! This is a sample of the manifest file:

    <?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. You can use a code like the following in App1.exe to launch the 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
    }
    

    ...and finally, this is the code of the Win32 function genWin32ShellExecute() I created to launch a process or open a document when using QT on a 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 讨论(0)
  • 2020-12-29 15:34

    See this question on elevating privileges only when required in C# and this article on User Account Control

    To sum it up: one needs to launch a new process with elevated permissions. The elevation level cannot be changed at runtime. Launching with elevated permissions is done either via WinAPI or embedding a correct manifest in the executable.

    0 讨论(0)
提交回复
热议问题