是否有 API 调用提示用户提升 UAC?
Is there an API call to prompt user for UAC elevation?
我的应用程序需要写入 \ProgramData 中可以保护的文件。这只会在安装后发生一次。
是否有 API 函数可以获取 ACL 信息并提示用户授权应用程序访问文件?换句话说,应用程序会要求 Windows 提示用户进行确认和授权。这应该以交互方式发生,并允许应用程序在授权访问文件后恢复执行。该应用程序以标准用户身份运行,不需要管理员权限。
文件使用 CreateFile() 打开。
编辑:我的查询与其他据说重复的查询之间存在细微差别。我正在请求访问一个特定对象(一个文件)的权限。其他人要求提升整个进程的特权。无论如何,我感谢所有包含解决方案的回复。
进程只能使用提升的令牌启动,事后无法获得它。因此,您可以使用命令行参数重新启动提升的应用程序,告诉它该做什么(简单的解决方案),或者实现一个进程外的 COM 服务器,您可以创建提升的并向它传递指令(更难)。
第三种解决方案是利用 IFileOperation
接口的内置 UAC 支持,但这不会让您 read/write,只能复制。因此,您可以复制需要修改的文件,修改副本,然后使用 IFileOperation
将临时文件复制到原始文件上。
如果您不想提升整个应用,您有以下几种选择:
生成一个单独的提升进程来访问该文件。将 ShellExecute/Ex()
与 runas
动词或 CreateProcessElevated()
一起使用到 运行 您的应用程序的第二个副本或另一个辅助应用程序,并使用命令行参数告诉它要做什么做。如果需要,主进程可以等待第二个进程退出。
创建一个COM对象来访问文件,然后使用COM Elevation Moniker来运行使COM对象处于提升状态。
使用 CredUIPromptForCredentials()
or CredUIPromptForWindowsCredentials()
(see Asking the User for Credentials for more details), then logon to the specified account using LogonUser()
to get a token, impersonate that token using ImpersonateLoggedOnUser()
, access the file as needed, and then stop impersonating using RevertToSelf()
and close the token with CloseHandle()
.
提示用户输入凭据
感谢@Remy 的 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);
}
我的应用程序需要写入 \ProgramData 中可以保护的文件。这只会在安装后发生一次。
是否有 API 函数可以获取 ACL 信息并提示用户授权应用程序访问文件?换句话说,应用程序会要求 Windows 提示用户进行确认和授权。这应该以交互方式发生,并允许应用程序在授权访问文件后恢复执行。该应用程序以标准用户身份运行,不需要管理员权限。
文件使用 CreateFile() 打开。
编辑:我的查询与其他据说重复的查询之间存在细微差别。我正在请求访问一个特定对象(一个文件)的权限。其他人要求提升整个进程的特权。无论如何,我感谢所有包含解决方案的回复。
进程只能使用提升的令牌启动,事后无法获得它。因此,您可以使用命令行参数重新启动提升的应用程序,告诉它该做什么(简单的解决方案),或者实现一个进程外的 COM 服务器,您可以创建提升的并向它传递指令(更难)。
第三种解决方案是利用 IFileOperation
接口的内置 UAC 支持,但这不会让您 read/write,只能复制。因此,您可以复制需要修改的文件,修改副本,然后使用 IFileOperation
将临时文件复制到原始文件上。
如果您不想提升整个应用,您有以下几种选择:
生成一个单独的提升进程来访问该文件。将
ShellExecute/Ex()
与runas
动词或CreateProcessElevated()
一起使用到 运行 您的应用程序的第二个副本或另一个辅助应用程序,并使用命令行参数告诉它要做什么做。如果需要,主进程可以等待第二个进程退出。创建一个COM对象来访问文件,然后使用COM Elevation Moniker来运行使COM对象处于提升状态。
使用
CredUIPromptForCredentials()
orCredUIPromptForWindowsCredentials()
(see Asking the User for Credentials for more details), then logon to the specified account usingLogonUser()
to get a token, impersonate that token usingImpersonateLoggedOnUser()
, access the file as needed, and then stop impersonating usingRevertToSelf()
and close the token withCloseHandle()
. 提示用户输入凭据
感谢@Remy 的 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);
}