一些以普通用户开始的应用程序会在需要的时候(例如文件pipe理器需要写这样的文件夹)请求提升权限,然后继续操作。
我怎样才能复制这种行为?
正如Tamás所指出的那样,您需要启动一个拥有更高权利的新流程。 过去我搜查了很多,但是我没有找到任何提升当前流程权利的方法。
比方说,你的主要应用程序是App1.exe,然后你调用一个辅助进程App2.exe需要提升的权利。
答:您可以在您的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操作系统上使用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
仅在C#中需要提升权限时才能看到此问题,而在“用户帐户控制”中则显示此篇文章
总结一下:需要用提升的权限启动一个新的进程。 高程级别不能在运行时更改。 使用提升的权限启动可以通过WinAPI完成,也可以在可执行文件中嵌入正确的清单。
简而言之:为Windows创建两个可执行文件。 常规的可执行文件,和一个worker exe文件,用来执行“提升”操作(通过传递命令行选项)。
对于第二个EXE文件,您添加一个具有<requestExecutionLevel level="requireAdministrator"/>
节点的应用程序清单文件。
启动worker应用程序时,确保使用包装ShellExecute的QT函数,而不是CreateProcess,因为CreateProcess只是无法启动requireAdministrator应用程序,而ShellExecute(作为一个shell函数)可以执行UAC提升提示。
也可以使用ActiveX控件来做到这一点,但正如你正在瞄准的Qt似乎不太合适。
您也可以在提升模式下启动COM对象。 有关更多信息,请参阅此MSDN文章 。