【问题标题】:How do you programmatically determine whether a Windows computer is a member of a domain?您如何以编程方式确定 Windows 计算机是否是域的成员?
【发布时间】:2010-09-17 09:31:25
【问题描述】:

我需要一种方法来确定运行我的程序的计算机是否加入了任何域。它属于哪个特定域并不重要,只要它是否连接到任何东西。我正在针对 Win32 API 使用 vc++ 进行编码。

【问题讨论】:

标签: c++ windows winapi dns


【解决方案1】:

直接来自微软:

How To Determine If a Windows NT/Windows 2000 Computer Is a Domain Member

此方法使用 Windows API。来自文章摘要:

本文介绍了如何 确定计算机是否 运行 Windows NT 4.0 或 Windows 2000 是域的成员,是成员 属于一个工作组,或者是一个独立的 使用本地安全的计算机 授权 API。

本文还提供了一个小程序的示例代码,用于输出运行该程序的计算机是域的一部分、工作组的一部分还是独立计算机。

【讨论】:

  • 请注意,如果您只想检查机器是否已加入域(并获取域名),则不需要 GENERIC_READ 权限。 GENERIC_READ 需要提升,而仅使用 POLICY_VIEW_LOCAL_INFORMATION 则不需要。
  • 该链接现在已断开。
【解决方案2】:

我认为NetServerEnum 功能将帮助您实现您想要的;我会要求 servertype 参数使用 SV_TYPE_DOMAIN_CTRL 常量的主域控制器。如果您没有得到任何信息,那么您不在域中。

【讨论】:

    【解决方案3】:

    MSDN 示例中的代码有些过时。这是我想出的有效功能。

    bool ComputerBelongsToDomain()
    {
        bool ret = false;
    
        LSA_OBJECT_ATTRIBUTES objectAttributes;
        LSA_HANDLE policyHandle;
        NTSTATUS status;
        PPOLICY_PRIMARY_DOMAIN_INFO info;
    
        // Object attributes are reserved, so initialize to zeros.
        ZeroMemory(&objectAttributes, sizeof(objectAttributes));
    
        status = LsaOpenPolicy(NULL, &objectAttributes, GENERIC_READ | POLICY_VIEW_LOCAL_INFORMATION, &policyHandle);
        if (!status)
        {
            status = LsaQueryInformationPolicy(policyHandle, PolicyPrimaryDomainInformation, (LPVOID*)&info);
            if (!status)
            {
                if (info->Sid)
                    ret = true;
    
                LsaFreeMemory(info);
            }
    
            LsaClose(policyHandle);
        }
    
        return ret;
    }
    

    【讨论】:

      【解决方案4】:

      这是一个我没有看到提到的非常简单的方法。

      TCHAR UserDnsDomain[128] = { 0 }; 
      DWORD Result = 0;
      
      Result = GetEnvironmentVariable("USERDNSDOMAIN", UserDnsDomain, sizeof(UserDnsDomain));
      
      if (Result == 0 || Result >= sizeof(UserDnsDomain) || GetLastError() == ERROR_ENVVAR_NOT_FOUND)
      {
          return(FALSE); // Not logged in to a domain
      }
      

      这是基于这样的想法,即如果运行此代码的用户当前未登录到域,则 USERDNSDOMAIN 环境变量将为空或不可用。但是您应该考虑一些注意事项。

      优点:

      • 非常容易实施。
      • 99% 可靠。

      缺点:

      • 如果计算机已加入域,但执行此代码的用户使用本地帐户登录到该计算机,则可能会失败或返回错误结果。
      • 如果计算机已加入域,但在登录/用户使用缓存凭据登录时与域控制器的网络连接不可用,则可能会失败或返回错误结果。

      【讨论】:

      • 如果运行命令的用户是SYSTEM,也可能会失败。
      【解决方案5】:

      您可以检查注册表项 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon 的“CachePrimaryDomain”值。

      【讨论】:

      • MSDN 说这个密钥从 Windows 2000 开始不再使用,但为了向后兼容而保留。这让我想知道它是否可以安全使用?
      • @kgriffs 它在我的机器上不可用。
      【解决方案6】:

      避免 LSA,这是一种错误的方法。 您必须使用 DS api(2 行代码)

      【讨论】:

      • 您是否有指向该 API 的 MSDN 页面的链接?
      • 我猜他指的是使用DSBind。请注意,它仅适用于 Vista/2008 及更高版本。
      【解决方案7】:

      从计算机的名称来看呢?

      编辑:这是一个很糟糕的“答案”。我的意思是检查计算机名称中的domain\name 形式。这当然意味着您确实知道域的名称,它并不能解决仅知道计算机是否在任何域中的问题。

      【讨论】:

      • 据我所知,所有 Windows 计算机都必须有一个名称,无论它们是否在网络上。
      猜你喜欢
      • 1970-01-01
      • 2012-07-07
      • 2010-09-26
      • 2015-10-14
      • 2012-02-21
      • 1970-01-01
      • 2011-01-03
      • 2010-11-15
      相关资源
      最近更新 更多