2013-01-02 8 views
11

完全修飾されたActive Directoryドメイン名からNETBIOSドメイン名を取得することは、時には面倒な作業です。私は良い答えを見つけたhere複雑な環境でFQDNを使用してNETBIOSドメイン名を取得する方法

複数のフォレストを持つ環境では、この方法は、PCがクエリしているフォレストにない場合は機能しません。これは、LDAP://RootDSEがコンピュータのドメインに関する情報を照会するためです。

何人か質問するかもしれません:どうしてこんなに複雑ですか?

ActiveDirectory.Domain.GetComputerDomain().Name; 

それともユーザーのドメイン名取得:

Environment.GetEnvironmentVariable("USERDOMAIN"); 

または

Environment.UserDomainName; 

をしかしNETBIOSドメイン名は、完全なものにできるのと同じことで取得された最初のドットの前に名前を使用しますあなたとあなたのコンピュータは異なるドメインまたはフォレストにあるかもしれません!したがって、このアプローチは単純な環境でのみ使用できます。

DJ KRAZE’sソリューションでは、クロスドメインクエリを可能にするために1つの小さな変更のみが必要です。これは信頼関係を前提としています!

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

また、あなたのためにすべての周りmonkeyingを行います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 /呼び出し:

[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

これは説明したように動作しますが、私は1つの変更を加えなければなりませんでした。構造体 'DomainControllerInfo'はクラスであったはずです。メソッド 'Marshal.PtrToStructure'はそれを義務付けました。 –

関連する問題