【发布时间】:2010-09-10 20:45:09
【问题描述】:
我需要我的应用程序根据 Vista UAC 是否启用而表现出不同的行为。我的应用程序如何检测用户计算机上的 UAC 状态?
【问题讨论】:
-
你能解释一下为什么需要这个吗?
-
例如,我有一个应用程序使用 API 连接到需要启用 UAC 才能工作的外部程序。如果 UAC 关闭,我想通过对话窗口通知用户。
标签: windows-vista uac
我需要我的应用程序根据 Vista UAC 是否启用而表现出不同的行为。我的应用程序如何检测用户计算机上的 UAC 状态?
【问题讨论】:
标签: windows-vista uac
检查 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System 中的注册表值
EnableLUA 值确定 UAC 是否处于活动状态。
【讨论】:
This post 在 C# 中有示例代码,用于测试 UAC 是否打开以及当前应用程序是否已获得提升的权限。您可以下载代码并根据需要进行解释。还链接了一个在 C++ 中显示相同的示例
http://www.itwriting.com/blog/198-c-code-to-detect-uac-elevation-on-vista.html
该帖子中的代码不只是从注册表中读取。如果启用了 UAC,您可能无权从注册表中读取它。
【讨论】:
AFAIK,UAC 是本地用户或组的策略设置。因此,您可以从 .Net 中读取此属性。很抱歉没有更多细节,但我希望这会有所帮助
【讨论】:
这个注册表项应该告诉你:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
值EnableLUA (DWORD)
1 已启用/0 或缺失已禁用
但这假设您有权阅读它。
您可以通过编程方式尝试读取用户的令牌并猜测它是否是启用了 UAC 的管理员(请参阅here)。并非万无一失,但它可能会起作用。
这里的问题更多的是“你为什么需要知道”——它与答案有关。实际上,没有 API,因为从操作系统行为的角度来看,重要的是用户是否是管理员 - 他们如何选择以管理员身份保护自己是他们的问题。
【讨论】:
您可以检查以下注册表项中的 DWORD 值 EnableLUA:
HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Policies/System
如果值为 0(或不存在),则 UAC 为 OFF。如果它存在且非零,则 UAC 为 ON:
BOOL IsUacEnabled( )
{
LPCTSTR pszSubKey = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
LPCTSTR pszValue = _T("EnableLUA");
DWORD dwType = 0;
DWORD dwValue = 0;
DWORD dwValueSize = sizeof( DWORD );
if ( ERROR_SUCCESS != SHGetValue( HKEY_LOCAL_MACHINE, pszSubKey, pszValueOn,
&dwType, &dwValue, &dwValueSize) )
{
return FALSE;
}
return dwValue != 0;
}
注意,如果用户改变了UAC的状态,但还没有重启电脑,这个函数会返回不一致的结果。
【讨论】:
您不想检查是否启用了 UAC;这并没有告诉你任何事情。
我可以成为禁用 UAC 的标准用户。
你要查if the user is running with administrative privileges using CheckTokenMembership:
///This function tells us if we're running with administrative permissions.
function IsUserAdmin: Boolean;
var
b: BOOL;
AdministratorsGroup: PSID;
begin
{
This function returns true if you are currently running with
admin privileges.
In Vista and later, if you are non-elevated, this function will
return false (you are not running with administrative privileges).
If you *are* running elevated, then IsUserAdmin will return
true, as you are running with admin privileges.
Windows provides this similar function in Shell32.IsUserAnAdmin.
But the function is depricated, and this code is lifted from the
docs for CheckTokenMembership:
http://msdn.microsoft.com/en-us/library/aa376389.aspx
}
{
Routine Description: This routine returns TRUE if the caller's
process is a member of the Administrators local group. Caller is NOT
expected to be impersonating anyone and is expected to be able to
open its own process and process token.
Arguments: None.
Return Value:
TRUE - Caller has Administrators local group.
FALSE - Caller does not have Administrators local group.
}
b := AllocateAndInitializeSid(
SECURITY_NT_AUTHORITY,
2, //2 sub-authorities
SECURITY_BUILTIN_DOMAIN_RID, //sub-authority 0
DOMAIN_ALIAS_RID_ADMINS, //sub-authority 1
0, 0, 0, 0, 0, 0, //sub-authorities 2-7 not passed
AdministratorsGroup);
if (b) then
begin
if not CheckTokenMembership(0, AdministratorsGroup, b) then
b := False;
FreeSid(AdministratorsGroup);
end;
Result := b;
end;
【讨论】:
这篇文章相当古老,但我想评论一下“你为什么需要知道”和“检查令牌成员资格”。
事实上,微软自己的文档说“如果用户帐户控制已关闭并且标准用户尝试执行需要提升的任务”,我们应该提供错误而不是显示按钮和/或链接尝试提升的 UAC 屏蔽。详情见底部http://msdn.microsoft.com/en-us/library/windows/desktop/aa511445.aspx。
如果不检查是否启用了 UAC,我们如何做到这一点?
也许在这种情况下检查用户是否以管理员权限运行是正确的,但谁知道呢? Microsoft 提供的指导充其量是不确定的,如果不是完全令人困惑的话。
【讨论】:
对于发现此问题并正在寻找 VBScript 解决方案的任何其他人。这是我想出的检测是否启用了 UAC,如果启用了,则以提升的权限重新启动我的脚本。只需将您的代码放在 Body() 函数中。如果我编写代码以始终启动提升,我发现 XP 和 Windows 7 之间的可移植性存在问题。如果没有 UAC,则使用此方法绕过海拔高度。还应考虑启用 UAC 的 2008 及更高版本的服务器。
On Error Resume Next
UACPath = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA"
Dim WshShell
Set WshShell = CreateObject("wscript.Shell")
UACValue = WshShell.RegRead(UACPath)
If UACValue = 1 Then
'Run Elevated
If WScript.Arguments.length =0 Then
Set objShell = CreateObject("Shell.Application")
'Pass a bogus argument with leading blank space, say [ uac]
objShell.ShellExecute "wscript.exe", Chr(34) & _
WScript.ScriptFullName & Chr(34) & " uac", "", "runas", 1
WScript.Quit
Else
Body()
End If
Else
Body()
End If
Function Body()
MsgBox "This is the body of the script"
End Function
【讨论】: