如何在运行时询问用户提升权限?

时间:2011-05-24 10:10:26

标签: c++ windows qt

某些应用程序(以常规用户启动)将在必要时请求提升权限(例如,文件管理器需要编写此类文件夹),然后继续执行操作。

我该如何复制这种行为?

4 个答案:

答案 0 :(得分:4)

正如Tamás所指出的那样,你需要推出一个拥有更高权利的新流程。我过去经常搜索,但我没有办法提升当前流程的权利。

假设您的主应用程序是App1.exe,然后您调用需要提升权限的辅助进程App2.exe。


:一种。您可以在App2.exe中嵌入清单,但更简单的方法是使用以下内容创建名为App2.exe.manifest的清单文件[文本文件],并将其放在与App2.exe相同的目录中。 注意: !!奇怪的是,如果您的应用程序的名称不是App2.exe而是App2_install.exe或App2_setup.exe(即,如果应用程序名称包含“安装”或“设置”),则Windows Vista / Windows 7中将自动显示UAC对话框即使没有明显的文件,也会要求提升权利! 这是清单文件的示例:

<?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中。您可以在App1.exe中使用以下代码来启动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
}

...最后,这是我创建的Win32函数genWin32ShellExecute()的代码,用于在Win32 O / S上使用QT时启动进程或打开文档:

标题:

#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

答案 1 :(得分:3)

请参阅this question on elevating privileges only when required in C#this article on User Account Control

总结一下:需要使用提升的权限启动新进程。高程级别无法在运行时更改。使用提升的权限启动可以通过WinAPI或在可执行文件中嵌入正确的清单来完成。

答案 2 :(得分:2)

简而言之:为Windows创建两个可执行文件。常规可执行文件,以及用于执行“提升”操作的worker exe文件(通过传递命令行选项)。

在第二个EXE文件中添加一个带有<requestExecutionLevel level="requireAdministrator"/>节点的应用程序清单文件。

启动worker应用程序时,请确保使用包装ShellExecute的QT函数,而不是CreateProcess,因为CreateProcess无法启动requireAdministrator应用程序,而ShellExecute(作为shell函数)可以执行UAC提升提示。

也可以使用ActiveX控件执行此操作,但是当您将Qt定位为不太合适时。

答案 3 :(得分:2)

您还可以在提升模式下启动COM对象。有关详细信息,请参阅此MSDN article