2013-01-02 16 views
11

NETBIOS etki alanı adını tam nitelikli bir Active Directory etki alanı adı almak bazen sıkıcı bir iştir. here iyi bir yanıt buldum.Karmaşık bir ortamda FQDN kullanarak NETBIOS etki alanı adı nasıl edinilir

Birden çok ormanı olan bir ortamda, bu yaklaşım, PC'yi sorguladığınız ormanda değilse işe yaramayacaktır. Bunun nedeni, LDAP://RootDSE bilgisayarın etki alanıyla ilgili bilgileri sorgulayacaktır.

Bazı sorular sorabilir: neden bu kadar karmaşık?

ActiveDirectory.Domain.GetComputerDomain().Name; 

Ya da sadece kullanıcının alan adını almak: Tamamen

Environment.GetEnvironmentVariable("USERDOMAIN"); 

veya

Environment.UserDomainName; 

ANCAK NETBIOS alanı adı olabilir şey sadece tarafından alınan ilk noktadan öncesi adı kullanmak farklı ve siz veya bilgisayarınız farklı bir alanda veya ormanda olabilir! Yani bu yaklaşım sadece basit bir ortamda kullanılabilir. Çapraz etki alanı sorgularına izin vermek için yalnızca küçük bir değişiklik yapılması gerekir. Bu güven ilişkisi var!

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

Sen Q & A biçimi veya bu yazmalıyım (muhtemelen) sizin Geliştirilmiş cevap orijinal soruyla gitmeli. –

+0

Düzenleme isteğim reddedildi çünkü "Düzenleme, orijinal yayında çok fazla değişiyor" – Daro

+0

Bunu ayrı bir yanıt olarak gönderin. Daha fazla temsilcisi olan biri daha sonra onları birleştirebilmelidir. –

cevap

8

Ayrıca sizin için tüm etrafında monkeying yapacak DsGetDcName API kullanabilirsiniz. Aynı zamanda aramaları önbelleğe alır ve sorguladığınız etki alanı yerel bilgisayarsa ağa bile vurmaz.

Eğer

Kullanım yeteneklerine ek gereksinimleri varsa:

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/çağır:

[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

Bu anlatıldığı şekilde çalışır, ancak bir değişiklik yapmam gerekiyordu: 'DomainControllerInfo' yapısı bir sınıf olmalıydı. 'Marshal.PtrToStructure' yöntemi onu zorunlu kılmıştır. –