2013-01-02 44 views
11

從完全限定的Active Directory域名獲取NETBIOS域名有時是一項繁瑣的任務。我找到了一個很好的答案here如何在複雜環境中使用FQDN獲取NETBIOS域名

在具有多個森林的環境中,如果PC不在您要查詢的森林中,則此方法無效。這是因爲LDAP://RootDSE將查詢計算機域的信息。

有人可能會問:爲什麼這麼複雜?

ActiveDirectory.Domain.GetComputerDomain().Name; 

或者只是得到了用戶的域名:

Environment.GetEnvironmentVariable("USERDOMAIN"); 

Environment.UserDomainName; 

但NETBIOS域名可以是一些完全只是檢索到的第一個點之前使用的名稱不同的,你或你的電腦可能在不同的域名或森林!所以這種方法僅適用於簡單的環境。

DJ KRAZE’s解決方案只需要一個小的修改來允許跨域查詢。這假設了一種信任關係!

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; 
    } 
+0

你應該在Q&A形式,或寫這個(可能)您改進的答案應該與原始問題一致。 –

+0

我的編輯請求被拒絕,因爲「原始帖子中的編輯變化太大」 – Daro

+0

將其作爲單獨的答案發布。有更多代表的人應該可以在稍後合併它們。 –

回答

8

您還可以使用DsGetDcName API,它會做周圍所有的胡鬧爲您服務。如果您查詢的域名是本地計算機,它也會緩存呼叫,甚至不會觸及網絡。

如果您對

使用的功能的其他要求:

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:

[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; 
+2

這個工作方式如上所述,但我不得不做一個改變:struct'DomainControllerInfo'應該是一個類。方法'Marshal.PtrToStructure'授權它。 –

相關問題