简体   繁体   English

如何在复杂环境中使用FQDN获取NETBIOS域名

[英]How to get the NETBIOS Domain Name using the FQDN in a Complex Environment

Getting the NETBIOS domain name from a fully qualified Active Directory domain name is sometimes a tedious task. 从完全限定的Active Directory域名获取NETBIOS域名有时是一项繁琐的工作。 I found a good answer here . 我在这里找到了一个好的答案。

In an environment with multiple forests this approach will however not work if the PC is not in the forest you are querying. 在具有多个林的环境中,如果PC不在您正在查询的林中,则此方法将不起作用。 This is because LDAP://RootDSE will query information for the computer's domain. 这是因为LDAP://RootDSE将查询计算机域的信息。

Some might ask: why so complicated? 有人可能会问:为什么这么复杂? Just use the name before the first dot retrieved by: 只需在检索到的第一个点之前使用该名称:

ActiveDirectory.Domain.GetComputerDomain().Name;

Or just get the user's domain name: 或者只是获取用户的域名:

Environment.GetEnvironmentVariable("USERDOMAIN");

or 要么

Environment.UserDomainName;

BUT the NETBIOS domain name can be something completely different, and you or your computer might be in a different domain or forest! 但是NETBIOS域名可能完全不同,您或您的计算机可能位于不同的域或林中! So this approach is usable only in a simple environment. 所以这种方法只能在简单的环境中使用。

DJ KRAZE's solution needs only one small modification to allow cross domain queries. DJ KRAZE的解决方案只需要一个小的修改就可以进行跨域查询。 This assumes a trust relationship! 这假设了一种信任关系!

private string GetNetbiosDomainName(string dnsDomainName)
{
      string netbiosDomainName = string.Empty;

      DirectoryEntry rootDSE = new DirectoryEntry(string.Format("LDAP://{0}/RootDSE",dnsDomainName));

      string configurationNamingContext = rootDSE.Properties["configurationNamingContext"][0].ToString();

      DirectoryEntry searchRoot = new DirectoryEntry("LDAP://cn=Partitions," + configurationNamingContext);

      DirectorySearcher searcher = new DirectorySearcher(searchRoot);
      searcher.SearchScope = SearchScope.OneLevel;
      searcher.PropertiesToLoad.Add("netbiosname");
      searcher.Filter = string.Format("(&(objectcategory=Crossref)(dnsRoot={0})(netBIOSName=*))", dnsDomainName);

      SearchResult result = searcher.FindOne();

      if (result != null)
      {
        netbiosDomainName = result.Properties["netbiosname"][0].ToString();
      }

      return netbiosDomainName;
    }

You can also use the DsGetDcName API, which will do all the monkeying around for you. 您还可以使用DsGetDcName API,它将为您完成所有的工作。 It will also cache calls and not even hit the network if the domain you are querying is the local computer. 如果您要查询的域是本地计算机,它还会缓存呼叫,甚至不会访问网络。

If you have additional requirements on the capabilities of the 如果您对该功能有其他要求

Use: 采用:

internal static string GetNetbiosNameForDomain(string dns)
{
    IntPtr pDomainInfo;
    int result = DsGetDcName(null, dns, IntPtr.Zero, null,
        DSGETDCNAME_FLAGS.DS_IS_DNS_NAME | DSGETDCNAME_FLAGS.DS_RETURN_FLAT_NAME,
        out pDomainInfo);
    try
    {
        if (result != ERROR_SUCCESS)
            throw new Win32Exception(result);

        var dcinfo = new DomainControllerInfo();
        Marshal.PtrToStructure(pDomainInfo, dcinfo);

        return dcinfo.DomainName;
    }
    finally
    {
        if (pDomainInfo != IntPtr.Zero)
            NetApiBufferFree(pDomainInfo);
    }
}

P/Invoke: 的P / Invoke:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private class DomainControllerInfo
{
    public string DomainControllerName;
    public string DomainControllerAddress;
    public int DomainControllerAddressType;
    public Guid DomainGuid;
    public string DomainName;
    public string DnsForestName;
    public int Flags;
    public string DcSiteName;
    public string ClientSiteName;
}

[Flags]
private enum DSGETDCNAME_FLAGS : uint
{
    DS_FORCE_REDISCOVERY = 0x00000001,
    DS_DIRECTORY_SERVICE_REQUIRED = 0x00000010,
    DS_DIRECTORY_SERVICE_PREFERRED = 0x00000020,
    DS_GC_SERVER_REQUIRED = 0x00000040,
    DS_PDC_REQUIRED = 0x00000080,
    DS_BACKGROUND_ONLY = 0x00000100,
    DS_IP_REQUIRED = 0x00000200,
    DS_KDC_REQUIRED = 0x00000400,
    DS_TIMESERV_REQUIRED = 0x00000800,
    DS_WRITABLE_REQUIRED = 0x00001000,
    DS_GOOD_TIMESERV_PREFERRED = 0x00002000,
    DS_AVOID_SELF = 0x00004000,
    DS_ONLY_LDAP_NEEDED = 0x00008000,
    DS_IS_FLAT_NAME = 0x00010000,
    DS_IS_DNS_NAME = 0x00020000,
    DS_RETURN_DNS_NAME = 0x40000000,
    DS_RETURN_FLAT_NAME = 0x80000000
}

[DllImport("Netapi32.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "DsGetDcNameW", CharSet = CharSet.Unicode)]
private static extern int DsGetDcName(
    [In] string computerName,
    [In] string domainName,
    [In] IntPtr domainGuid,
    [In] string siteName,
    [In] DSGETDCNAME_FLAGS flags,
    [Out] out IntPtr domainControllerInfo);

[DllImport("Netapi32.dll")]
private static extern int NetApiBufferFree(
    [In] IntPtr buffer);

private const int ERROR_SUCCESS = 0;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM