【发布时间】:2011-08-31 19:39:08
【问题描述】:
一些以普通用户启动的应用程序会在必要时请求提升权限(例如文件管理器需要写入此类文件夹),然后继续操作。
如何复制这种行为?
【问题讨论】:
一些以普通用户启动的应用程序会在必要时请求提升权限(例如文件管理器需要写入此类文件夹),然后继续操作。
如何复制这种行为?
【问题讨论】:
正如 Tamás 指出的那样,您需要启动一个具有更高权限的新流程。过去我搜索了很多,但我没有找到任何方法来提升当前进程的权限。
假设您的主要应用是 App1.exe,然后您调用需要提升权限的辅助进程 App2.exe。
A.您可以在 App2.exe 中嵌入清单,但更简单的方法是使用以下内容创建一个名为 App2.exe.manifest 的清单文件 [文本文件],并将其放在与 App2.exe 相同的目录中。 笔记: !!奇怪的是,如果您的应用程序的名称不是 App2.exe 而是 App2_install.exe 或 App2_setup.exe(即如果应用程序名称包含“安装”或“设置”),则 UAC 对话框将在 Windows Vista / Windows 7 中自动出现即使没有清单文件也会要求提升权限! 这是清单文件的示例:
<?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
【讨论】:
见this question on elevating privileges only when required in C#和this article on User Account Control
总结一下:需要启动一个具有提升权限的新进程。运行时无法更改海拔高度。通过 WinAPI 或在可执行文件中嵌入正确的清单来以提升的权限启动。
【讨论】:
简而言之:为 windows 创建两个可执行文件。常规可执行文件和用于执行“提升”操作(通过传递命令行选项)的工作 exe 文件。
向第二个 EXE 文件添加一个带有 <requestExecutionLevel level="requireAdministrator"/> 节点的应用程序清单文件。
启动工作应用程序时,请确保使用包装 ShellExecute 的 QT 函数,而不是 CreateProcess,因为 CreateProcess 根本无法启动 requireAdministrator 应用程序,而 ShellExecute(作为 shell 函数)可以执行 UAC 提升提示。
也可以使用 ActiveX 控件执行此操作,但由于您的目标是 Qt,这似乎不太合适。
【讨论】:
您还可以在提升模式下启动 COM 对象。有关更多信息,请参阅此MSDN article。
【讨论】: