2012-06-13 34 views
2

我的應用程序正在加入到Active Directory域的計算機上運行。有沒有辦法使用WinAPI方法獲取該域名的DNS名稱?我希望即使沒有可用的DNS服務器或域控制器也能正常工作。WinAPI相當於Win32_ComputerSystem.Domain

現在,我能找到的唯一途徑就是通過的Win32_ComputerSystem WMI類的域屬性:

using System.Management; 

public class WMIUtility 
{ 
    public static ManagementScope GetDefaultScope(string computerName) 
    { 
     ConnectionOptions connectionOptions = new ConnectionOptions(); 
     connectionOptions.Authentication = AuthenticationLevel.PacketPrivacy; 
     connectionOptions.Impersonation = ImpersonationLevel.Impersonate; 
     string path = string.Format("\\\\{0}\\root\\cimv2", computerName); 
     return new ManagementScope(path, connectionOptions); 
    } 

    public static ManagementObject GetComputerSystem(string computerName) 
    { 
     string path = string.Format("Win32_ComputerSystem.Name='{0}'", computerName); 
     return new ManagementObject(
      GetDefaultScope(computerName), 
      new ManagementPath(path), 
      new ObjectGetOptions() 
     ); 
    } 

    public static string GetDNSDomainName(string computerName) 
    { 
     using (ManagementObject computerSystem = GetComputerSystem(computerName)) 
     { 
      object isInDomain = computerSystem.Properties["PartOfDomain"].Value; 
      if (isInDomain == null) return null; 
      if(!(bool)isInDomain) return null; 
      return computerSystem.Properties["Domain"].Value.ToString(); 
     } 
    } 
} 

我可以在WinAPI的找到的唯一的事情是NetGetJoinInformation方法,它返回NetBIOS域名:

using System.Runtime.InteropServices; 

public class PInvoke 
{ 
    public const int NERR_SUCCESS = 0; 

    public enum NETSETUP_JOIN_STATUS 
    { 
     NetSetupUnknownStatus = 0, 
     NetSetupUnjoined, 
     NetSetupWorkgroupName, 
     NetSetupDomainName 
    } 

    [DllImport("netapi32.dll", CharSet = CharSet.Unicode)] 
    protected static extern int NetGetJoinInformation(string lpServer, out IntPtr lpNameBuffer, out NETSETUP_JOIN_STATUS BufferType); 

    [DllImport("netapi32.dll", SetLastError = true)] 
    protected static extern int NetApiBufferFree(IntPtr Buffer); 

    public static NETSETUP_JOIN_STATUS GetComputerJoinInfo(string computerName, out string name) 
    { 
     IntPtr pBuffer; 
     NETSETUP_JOIN_STATUS type; 
     int lastError = NetGetJoinInformation(computerName, out pBuffer, out type); 
     if(lastError != NERR_SUCCESS) 
     { 
      throw new System.ComponentModel.Win32Exception(lastError); 
     } 
     try 
     { 
      if(pBuffer == IntPtr.Zero) 
      { 
       name = null; 
      } 
      else 
      { 
       switch(type) 
       { 
        case NETSETUP_JOIN_STATUS.NetSetupUnknownStatus: 
        case NETSETUP_JOIN_STATUS.NetSetupUnjoined: 
        { 
         name = null; 
         break; 
        } 
        default: 
        { 
         name = Marshal.PtrToStringUni(pBuffer); 
         break; 
        } 
       } 
      } 
      return type; 
     } 
     finally 
     { 
      if(pBuffer != IntPtr.Zero) 
      { 
       NetApiBufferFree(pBuffer); 
      } 
     } 
    } 
} 
+0

因此,您不想解析名稱,而是獲取計算機所屬域的名稱,我是否明白這一點?即當機器執行自己的動態DNS註冊時,後綴會附加到DNS名稱上? – 0xC0000022L

+0

@STATUS_ACCESS_DENIED正確的,計算機所屬的域。我編輯了這個問題,試圖說明這一點。 –

回答

2

我覺得你與ComputerNameDnsDomain作爲第一個參數期待看到的東西GetComputerNameEx。但有可能你需要其他類型的其中一種。仍然,GetComputerNameEx是您從我如何理解問題尋找的功能。

PInvoke詳細信息here

您在您的評論提出一個合理的點,所以肯定的是,在這種情況下LsaQueryInformationPolicyPolicyDnsDomainInformation可能是更好的方式來獲得其中的計算機所屬的域的DNS名稱。

但這是一個特例,您的問題沒有提到任何這種特殊情況。只有在設置了主DNS後綴並且與計算機所屬的DNS域名不同的情況下才會這樣。對於所有實際用途GetComputerNameEx將完全按照您的要求進行。

+0

在GetComputerNameEx的備註部分中,它說:「如果您使用的環境使用不同的DNS佈局,而計算機的FQDN與其域的FQDN不匹配,請改用LsaQueryInformationPolicy」。我認爲LsaQueryInformationPolicy是我正在尋找的。 –

+0

夠公平的,至少我讓你走上正軌。請記住:沒有人可以從問題中知道這些細節,因爲你給它:) – 0xC0000022L

+0

我的問題可能不是那麼清楚,但我認爲要求相當於Win32_ComputerSystem.Domain給了一個非常清楚描述我所要求的內容。根據我給出的報價,看起來GetComputerNameEx可能會返回與Win32_ComputerSystem.Domain不同的內容。 –