【问题标题】:How to detect whether Vista UAC is enabled?如何检测Vista UAC是否开启?
【发布时间】:2010-09-10 20:45:09
【问题描述】:

我需要我的应用程序根据 Vista UAC 是否启用而表现出不同的行为。我的应用程序如何检测用户计算机上的 UAC 状态?

【问题讨论】:

  • 你能解释一下为什么需要这个吗?
  • 例如,我有一个应用程序使用 API 连接到需要启用 UAC 才能工作的外部程序。如果 UAC 关闭,我想通过对话窗口通知用户。

标签: windows-vista uac


【解决方案1】:

检查 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System 中的注册表值

EnableLUA 值确定 UAC 是否处于活动状态。

【讨论】:

    【解决方案2】:

    This post 在 C# 中有示例代码,用于测试 UAC 是否打开以及当前应用程序是否已获得提升的权限。您可以下载代码并根据需要进行解释。还链接了一个在 C++ 中显示相同的示例

    http://www.itwriting.com/blog/198-c-code-to-detect-uac-elevation-on-vista.html

    该帖子中的代码不只是从注册表中读取。如果启用了 UAC,您可能无权从注册表中读取它。

    【讨论】:

      【解决方案3】:

      AFAIK,UAC 是本地用户或组的策略设置。因此,您可以从 .Net 中读取此属性。很抱歉没有更多细节,但我希望这会有所帮助

      【讨论】:

        【解决方案4】:

        这个注册表项应该告诉你:

        HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
        

        EnableLUA (DWORD)

        1 已启用/0 或缺失已禁用

        但这假设您有权阅读它。

        您可以通过编程方式尝试读取用户的令牌并猜测它是否是启用了 UAC 的管理员(请参阅here)。并非万无一失,但它可能会起作用。

        这里的问题更多的是“你为什么需要知道”——它与答案有关。实际上,没有 API,因为从操作系统行为的角度来看,重要的是用户是否是管理员 - 他们如何选择以管理员身份保护自己是他们的问题。

        【讨论】:

        • 这是一个陷阱 22。如果启用了 UAC,您可能无权阅读它。
        • 一个小修正:注册表键是 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System,EnableLUA 是一个 DWORD 值(它不是键)。 HTH
        • 您应该使用 != 0 而不是根据 google chrome 源代码与 1 进行比较(显然有些系统的值 >1)
        • @RyanFarley 看起来密钥继承的 ACL 为所有用户提供了完全读取权限,因此只有在有人更改了 ACL 时才会出现读取问题。
        • 在我的 Windows 7 64 位机器上,可以在没有此密钥的情况下启用 UAC。我猜我的 UAC 是通过组策略启用的。我相信这对于 Vista 来说也是如此。
        【解决方案5】:

        您可以检查以下注册表项中的 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的状态,但还没有重启电脑,这个函数会返回不一致的结果。

        【讨论】:

          【解决方案6】:

          您不想检查是否启用了 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;
          

          【讨论】:

            【解决方案7】:

            这篇文章相当古老,但我想评论一下“你为什么需要知道”和“检查令牌成员资格”。

            事实上,微软自己的文档说“如果用户帐户控制已关闭并且标准用户尝试执行需要提升的任务”,我们应该提供错误而不是显示按钮和/或链接尝试提升的 UAC 屏蔽。详情见底部http://msdn.microsoft.com/en-us/library/windows/desktop/aa511445.aspx

            如果不检查是否启用了 UAC,我们如何做到这一点?

            也许在这种情况下检查用户是否以管理员权限运行是正确的,但谁知道呢? Microsoft 提供的指导充其量是不确定的,如果不是完全令人困惑的话。

            【讨论】:

              【解决方案8】:

              对于发现此问题并正在寻找 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
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-08-16
                • 1970-01-01
                相关资源
                最近更新 更多