是否有API调用来提示用户进行UAC提升?

时间:2015-08-05 23:43:56

标签: winapi uac

我的应用需要写入\ ProgramData中可以保护的文件。这只在安装后发生一次。

是否有一个API函数可以获取ACL信息并提示用户授权应用程序访问该文件?换句话说,应用程序会要求Windows提示用户进行确认和授权。这应该以交互方式发生,并允许应用程序在授权访问文件后继续执行。该应用程序以标准用户身份运行,不需要管理员权限。

使用CreateFile()打开文件。

编辑:我的查询与其他人之间存在细微差别,据说是重复的。我要求访问一个特定对象,一个文件的权限。其他人要求提升整个过程的特权。无论如何,我很感激所有包含解决方案的回复。

3 个答案:

答案 0 :(得分:12)

如果您不想提升整个应用,可以选择以下几种方法:

  1. 只是为了访问该文件而产生一个单独的提升过程。将ShellExecute/Ex()runas动词或CreateProcessElevated()一起使用,可以使用命令行参数运行应用程序的第二个副本或其他帮助程序应用程序,以告诉它该怎么做。如果需要,主进程可以等待第二个进程退出。

  2. 创建一个COM对象来访问该文件,然后使用COM Elevation Moniker以提升状态运行COM对象。

  3. 使用CredUIPromptForCredentials()CredUIPromptForWindowsCredentials()提示用户提供凭据(有关详细信息,请参阅Asking the User for Credentials),然后使用LogonUser()登录指定的帐户以获取令牌,使用ImpersonateLoggedOnUser()模拟该令牌,根据需要访问该文件,然后使用RevertToSelf()停止模拟并使用CloseHandle()关闭令牌。

答案 1 :(得分:4)

进程只能使用提升的令牌启动,但事后却无法获得。因此,您可以通过命令行参数重新启动应用程序,告诉它该做什么(简单的解决方案),或者实现一个可以创建提升并向其传递指令的进程外COM服务器(更难)。 / p>

第三种解决方案是利用IFileOperation接口的内置UAC支持,但这不允许您读/写,只能复制。因此,您可以复制需要修改的文件,修改副本,然后使用IFileOperation将临时文件复制到原始文件上。

答案 2 :(得分:4)

感谢@Exmy提供的ShellExecuteEx建议,这里有肮脏的细节。注意使用'cmd'和双命令,因此用户只需回复一次。此外,[1]必须等待进程完成,否则您可能会发现自己在删除文件之前创建了文件,并且[2]如果失败则不等待进程。

// delete file with Admin privilege
// 'file_name' is path of file to be deleted
SHELLEXECUTEINFO shex;
char param[512];
char *cmd = "/C \"attrib -H \"%s\" && del /F /Q \"%s\"\""; // double command

_snprintf(param, sizeof(param), cmd, file_name, file_name);
ZeroMemory(&shex, sizeof(shex));
shex.cbSize = sizeof(shex);
shex.lpVerb = "runas";  // runas, open
shex.lpFile = "cmd";    // not 'del'
shex.lpParameters = param;
shex.nShow = SW_HIDE;
shex.fMask = SEE_MASK_NOCLOSEPROCESS;
BOOL retshx = ShellExecuteEx(&shex);
// wait otherwise could return before completed
if(retshx)
{   time_t st = clock();
    DWORD exitCode;
    do
    {   if(!GetExitCodeProcess(shex.hProcess, &exitCode))
            break;
        if(clock() - st > CLOCKS_PER_SEC * 5)       // max 5 seconds
            break;
    } while(exitCode != STATUS_WAIT_0); // STILL_ACTIVE
    CloseHandle(shex.hProcess);
}