【问题标题】:Best way to get the connected network domain name in Windows在 Windows 中获取已连接网络域名的最佳方法
【发布时间】:2019-11-04 17:53:30
【问题描述】:

我想了解本地 Windows 系统是否连接到网络域(而不是工作组),如果是,请读取该域的名称。

我找到了这些 Windows API 函数来实现这一点:

  GetEnvironmentVariable('USERDNSDOMAIN')
  NetGetJoinInformation
  NetServerGetInfo
  NetWkstaGetInfo
  LookupAccountSid

它们之间有什么优点或缺点吗? (更快、更可靠、更准确……)

你会推荐哪一个?为什么?

【问题讨论】:

    标签: windows winapi


    【解决方案1】:

    LookupAccountSid 更专注于搜索 sid,NetServerGetInfo 专注于检索服务器信息。 所以这些都不适合你。

    域名从NetGetJoinInformation获取,NetWkstaGetInfo对应USERDOMAIN而不是USERDNSDOMAIN,具体看你想要的域名。

    GetEnvironmentVariable是只获取变量值的函数,可以随时被SetEnvironmentVariable修改(虽然我们平时不这样做),所以不推荐。

    无需特殊的组成员身份即可成功执行 NetGetJoinInformation函数。

    而且比NetWkstaGetInfo更纯净(根据你的要求)

    【讨论】:

      【解决方案2】:

      这里最直接和最有效 - 使用 PolicyDnsDomainInformation 致电 LsaQueryInformationPolicy。在输出时,你得到了 POLICY_DNS_DOMAIN_INFO 结构。这里将是主域的名称和 DNS 名称。还有它SID

      如果与策略对象关联的计算机不是 域,除 Name 之外的所有结构成员均为 NULL 或零。

      #include <Ntsecapi.h>
      
      NTSTATUS PrintDomainName()
      {
          LSA_HANDLE PolicyHandle;
      
          static LSA_OBJECT_ATTRIBUTES oa = { sizeof(oa) };
      
          NTSTATUS status = LsaOpenPolicy(0, &oa, POLICY_VIEW_LOCAL_INFORMATION, &PolicyHandle);
      
          if (LSA_SUCCESS(status))
          {
              PPOLICY_DNS_DOMAIN_INFO ppddi;
      
              if (LSA_SUCCESS(status = LsaQueryInformationPolicy(PolicyHandle, PolicyDnsDomainInformation, (void**)&ppddi)))
              {
                  if (ppddi->Sid)
                  {
                      DbgPrint("DnsDomainName: %wZ\n", &ppddi->DnsDomainName);
                  }
                  else
                  {
                      DbgPrint("%wZ: not a member of a domain\n", &ppddi->Name);
                  }
      
                  LsaFreeMemory(ppddi);
      
              }
      
              LsaClose(PolicyHandle);
          }
      
          return status;
      }
      

      NetGetJoinInformation 在内部执行相同的操作 - 查询 PolicyDnsDomainInformation,但不是在您的而是在远程进程中执行此操作(svchost.exe -k networkservice -p -s LanmanWorkstation - LanmanWorkstation 服务)和许多额外的调用。因此效率较低,但调用此 api 的源代码较少

      【讨论】:

      • 我不太明白你的解释(我认为那里有些词混淆了......)。你能检查一下吗?此外,LsaQueryInformationPolicy 需要先加载 Advapi32.dll。这不会比使用默认已加载的 dll 中的方法慢吗?
      • @CodeX - 不,直接调用LsaOpenPolicy + LsaQueryInformationPolicy + LsaFreeMemory + LsaCloseNetGetJoinInformation 调用相比会快得多 - 因为无论如何都在这条路径中调用了所有这些 +额外的远程调用 + 许多其他额外的调用
      • @CodeX - 默认情况下仅加载 ntdll.dll,例如 NetGetJoinInformation 需要加载 Wkscli.dll 及其所有依赖项.. 这将更多比较 advapi32.dll。然而,尽管使用 Lsa api 效率更高 - 在单次通话中您不会看到很大的差异。但更多 dll(潜在)将再次出现在 Net 案例中
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-12
      • 2016-07-11
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      相关资源
      最近更新 更多