如何在运行时向用户请求提升权限?

发布于 2024-11-09 09:15:52 字数 79 浏览 0 评论 0原文

某些以普通用户启动的应用程序会在必要时请求提升权限(例如文件管理器需要写入此类文件夹),然后继续操作。

我怎样才能复制这种行为?

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 operation.

How can I replicate this behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

滥情稳全场 2024-11-16 09:15:52

正如 Tamás 指出的那样,您需要启动一个具有更高权利的新流程。我过去进行了很多搜索,但没有找到任何方法来提升当前进程的权限。

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


A.您可以在 App2.exe 中嵌入清单,但更简单的方法是创建一个名为 App2.exe.manifest 的清单文件[文本文件],其中包含以下内容,并将其放在与 App2.exe 相同的目录中。
笔记: !!奇怪的是,如果您的应用程序名称不是 App2.exe,而是 App2_install.exe 或 App2_setup.exe(即,如果应用程序名称包含“install”或“setup”),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 操作系统上使用 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

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
匿名。 2024-11-16 09:15:52

请参阅有关仅在 C# 中需要时提升权限的问题这篇关于用户帐户控制的文章

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

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.

反话 2024-11-16 09:15:52

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

在第二个 EXE 文件中添加一个带有 节点。

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

也可以使用 ActiveX 控件来完成此操作,但由于您的目标是 Qt,这似乎不太合适。

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.

坦然微笑 2024-11-16 09:15:52

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文