2009-05-29 21 views

Trả lời

24

Bạn có thể PInvoke để Win32 như của API như NetGetDcName mà sẽ trả về một null/chuỗi rỗng cho một máy không miền tham gia.

Thậm chí tốt hơn là NetGetJoinInformation sẽ cho bạn biết rõ ràng nếu máy không được kết nối, trong nhóm làm việc hoặc trong miền.

Sử dụng NetGetJoinInformation tôi đặt lại với nhau này, mà làm việc cho tôi:

public class Test 
{ 
    public static bool IsInDomain() 
    { 
     Win32.NetJoinStatus status = Win32.NetJoinStatus.NetSetupUnknownStatus; 
     IntPtr pDomain = IntPtr.Zero; 
     int result = Win32.NetGetJoinInformation(null, out pDomain, out status); 
     if (pDomain != IntPtr.Zero) 
     { 
      Win32.NetApiBufferFree(pDomain); 
     } 
     if (result == Win32.ErrorSuccess) 
     { 
      return status == Win32.NetJoinStatus.NetSetupDomainName; 
     } 
     else 
     { 
      throw new Exception("Domain Info Get Failed", new Win32Exception()); 
     } 
    } 
} 

internal class Win32 
{ 
    public const int ErrorSuccess = 0; 

    [DllImport("Netapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)] 
    public static extern int NetGetJoinInformation(string server, out IntPtr domain, out NetJoinStatus status); 

    [DllImport("Netapi32.dll")] 
    public static extern int NetApiBufferFree(IntPtr Buffer); 

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

} 
+1

Tuyệt. Nhưng không có rò rỉ bộ nhớ nào trong hàm của bạn, dữ liệu pDomain được trả về bởi NetGetJoinInformation? – DSO

+0

(không phải vấn đề rò rỉ quá nhiều ...vì tôi sẽ gọi nó một lần và lưu vào bộ nhớ đệm) – DSO

+0

Ahh - mẫu mã mà tôi đã tấn công này từ trang PInvoke đang gọi NetApiBufferFree - tôi đã thêm nó vào mẫu =) – Rob

6
ManagementObject cs; 
     using(cs = new ManagementObject("Win32_ComputerSystem.Name='" + System.Environment.MachineName + "'")) 
     { 
      cs.Get(); 
      Console.WriteLine("{0}",cs["domain"].ToString()); 
     } 

Điều đó sẽ cho phép bạn lấy miền. Tôi tin rằng nó sẽ là rỗng hoặc trống nếu bạn là một phần của một nhóm làm việc và không phải là một miền.

Hãy chắc chắn để tham khảo System.Management

+0

Nó trả về "WORKGROUP" nếu không có trong miền. Điều này sẽ làm việc (trừ khi bạn đang ở trong một tên miền "WORKGROUP"!), Nhưng tôi sẽ chờ đợi một chút để xem nếu có một phương pháp tiếp cận không dựa trên WMI trước khi chọn nó như là câu trả lời đúng. – DSO

+0

Cảm ơn bạn đã cho tôi biết. Tôi chỉ có máy làm việc của mình để kiểm tra và tôi không thể xóa chính xác nó khỏi miền để kiểm tra. – Stephan

+2

Tôi nghĩ rằng điều này sẽ không hiệu quả. Nó chỉ ra rằng tên của nhóm làm việc cho hộp kiểm tra của tôi thực sự là WORKGROUP. Tôi nghĩ rằng nó trả về tên nhóm làm việc, không phải là một giá trị cố định, mà từ một quan điểm API có ý nghĩa hơn, nhưng nó có nghĩa là bạn không thể sử dụng nó để xác định liệu miền của nó có tham gia hay không. – DSO

3

Các biến môi trường có thể làm việc cho bạn.

Environment.UserDomainName 

MSDN Link để biết thêm chi tiết.

Environment.GetEnvironmentVariable("USERDNSDOMAIN") 

Tôi không chắc chắn biến môi trường này tồn tại mà không nằm trong miền.

Khắc phục sự cố nếu tôi sai Máy tính bảng quản trị viên Windows - Tôi tin rằng máy tính có thể nằm trong một số miền để có thể quan trọng hơn để biết tên miền nào, nếu có, thay vì ở trong bất kỳ nào miền.

+1

Theo như tôi biết máy tính chỉ có thể được nối với * một * miền - nhưng bạn có thể đăng nhập vào PC bằng thông tin xác thực từ nhiều miền trong rừng đó hoặc từ nhiều khu rừng nếu có tín thác lên. Tất cả đều hơi phức tạp một chút mặc dù =) – Rob

+1

Environment.UserDomainName trả về tên máy tính nếu máy không được nối với miền. Tôi cho rằng tôi có thể so sánh điều đó với Environment.MachineName để xác định xem tên miền của nó có tham gia hay không, nhưng tôi không chắc liệu điều đó có đúng trong mọi tình huống hay không. – DSO

+3

@ DSO - Tôi biết tôi đang nói chuyện muộn ở đây nhưng chỉ trong trường hợp ai đó tình cờ gặp chủ đề này, tôi chỉ muốn đề cập đến ngay cả trên máy tính đã tham gia miền nếu tài khoản người dùng đang chạy dưới tài khoản cục bộ hoặc hệ thống tài khoản, bạn không thể dựa vào UserDomainName! = MachineName. – Josh

85

Đừng đánh lừa bằng pinvoke nếu bạn không phải làm vậy.

Reference System.DirectoryServices, sau đó gọi:

System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain() 

Ném một ActiveDirectoryObjectNotFoundException nếu máy không phải là miền tham gia. Đối tượng Miền được trả về có chứa thuộc tính Tên mà bạn đang tìm kiếm.

+3

Tôi luôn luôn thích thấy rằng tồn tại một phiên bản quản lý của hầu như bất cứ điều gì. –

+9

Lưu ý cho người khác .. ** đảm bảo bạn sử dụng GetComputerDomain() ** (như đề xuất ở trên) và ** không GetCurrentDomain() **. GetCurrentDomain() chặn các độ tuổi nếu bạn không tham gia vào một miền. – James

+3

Có sự cố với cuộc gọi này vì mất khoảng 2 phút trên nhiều cấu hình. –

4

Chỉ muốn thả Mã Rob trong VB:

Public Class Test 
    Public Function IsInDomain() As Boolean 
     Try 
      Dim status As Win32.NetJoinStatus = Win32.NetJoinStatus.NetSetupUnknownStatus 
      Dim pDomain As IntPtr = IntPtr.Zero 
      Dim result As Integer = Win32.NetGetJoinInformation(Nothing, pDomain, status) 

      If (pDomain <> IntPtr.Zero) Then 
       Win32.NetApiBufferFree(pDomain) 
      End If 

      If (result = Win32.ErrorSuccess) Then 
       If (status = Win32.NetJoinStatus.NetSetupDomainName) Then 
        Return True 
       Else 
        Return False 
       End If 
      Else 
       Throw New Exception("Domain Info Get Failed") 
      End If 
     Catch ex As Exception 
      Return False 
     End Try 
    End Function 
End Class 
Public Class Win32 
    Public Const ErrorSuccess As Integer = 0 
    Declare Auto Function NetGetJoinInformation Lib "Netapi32.dll" (ByVal server As String, ByRef IntPtr As IntPtr, ByRef status As NetJoinStatus) As Integer 
    Declare Auto Function NetApiBufferFree Lib "Netapi32.dll" (ByVal Buffer As IntPtr) As Integer 
    Public Enum NetJoinStatus 
     NetSetupUnknownStatus = 0 
     NetSetupUnjoined 
     NetSetupWorkgroupName 
     NetSetupDomainName 
    End Enum 
End Class 

Như Vâng như mã Stephan đây:

Dim cs As System.Management.ManagementObject 
    Try 
     cs = New System.Management.ManagementObject("Win32_ComputerSystem.Name='" + System.Environment.MachineName + "'") 
     cs.Get() 
     dim myDomain as string = = cs("domain").ToString 
    Catch ex As Exception 
    End Try 


Tôi tin rằng chỉ có các mã thứ hai sẽ cho phép bạn biết những gì miền máy đã tham gia, ngay cả khi người dùng hiện tại KHÔNG PHẢI là thành viên miền.

2

Đây là phương pháp của tôi với xử lý/nhận xét ngoại lệ mà tôi đã phát triển dựa trên một số câu trả lời trong bài đăng này.

  1. Đưa bạn tên miền mà máy tính được kết nối.
  2. Chỉ trả về tên miền nếu người dùng thực sự đăng nhập vào tài khoản miền.

    /// <summary> 
    /// Returns the domain of the logged in user. 
    /// Therefore, if computer is joined to a domain but user is logged in on local account. String.Empty will be returned. 
    /// Relavant StackOverflow Post: http://stackoverflow.com/questions/926227/how-to-detect-if-machine-is-joined-to-domain-in-c 
    /// </summary> 
    /// <seealso cref="GetComputerDomainName"/> 
    /// <returns>Domain name if user is connected to a domain, String.Empty if not.</returns> 
    static string GetUserDomainName() 
    { 
        string domain = String.Empty; 
        try 
        { 
         domain = Environment.UserDomainName; 
         string machineName = Environment.MachineName; 
    
         if (machineName.Equals(domain,StringComparison.OrdinalIgnoreCase)) 
         { 
          domain = String.Empty; 
         } 
        } 
        catch 
        { 
         // Handle exception if desired, otherwise returns null 
        } 
        return domain; 
    } 
    
    /// <summary> 
    /// Returns the Domain which the computer is joined to. Note: if user is logged in as local account the domain of computer is still returned! 
    /// </summary> 
    /// <seealso cref="GetUserDomainName"/> 
    /// <returns>A string with the domain name if it's joined. String.Empty if it isn't.</returns> 
    static string GetComputerDomainName() 
    { 
        string domain = String.Empty; 
        try 
        { 
         domain = System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain().Name; 
        } 
        catch 
        { 
         // Handle exception here if desired. 
        } 
        return domain; 
    } 
    
1

Bạn có thể muốn thử sử dụng lĩnh vực DomainRole WMI. Giá trị 0 và 2 cho thấy máy trạm độc lập và máy chủ độc lập tương ứng.

Chúng tôi đang sử dụng này cho XIA Cấu hình phần mềm kiểm toán mạng của chúng tôi vì vậy tôi đã cribbed phương pháp ở đây ...

/// <summary> 
/// Determines whether the local machine is a member of a domain. 
/// </summary> 
/// <returns>A boolean value that indicated whether the local machine is a member of a domain.</returns> 
/// <remarks>http://msdn.microsoft.com/en-gb/library/windows/desktop/aa394102(v=vs.85).aspx</remarks> 
public bool IsDomainMember() 
{ 
    ManagementObject ComputerSystem; 
    using (ComputerSystem = new ManagementObject(String.Format("Win32_ComputerSystem.Name='{0}'", Environment.MachineName))) 
    { 
     ComputerSystem.Get(); 
     UInt16 DomainRole = (UInt16)ComputerSystem["DomainRole"]; 
     return (DomainRole != 0 & DomainRole != 2); 
    } 
} 
3

Bạn có thể kiểm tra tài sản của lớp Win32_ComputerSystem WMI PartOfDomain. Các MSDN nói:

PartOfDomain

Data type: boolean

Tiếp cận loại: Read-only

Nếu Đúng vậy, máy tính là một phần của một tên miền. Nếu giá trị là NULL, máy tính không nằm trong miền hoặc trạng thái không xác định. Nếu bạn bỏ tham gia máy tính khỏi miền, giá trị sẽ trở thành sai.

/// <summary> 
/// Determines whether the local machine is a member of a domain. 
/// </summary> 
/// <returns>A boolean value that indicated whether the local machine is a member of a domain.</returns> 
/// <remarks>http://msdn.microsoft.com/en-us/library/windows/desktop/aa394102%28v=vs.85%29.aspx</remarks> 
public bool IsDomainMember() 
{ 
    ManagementObject ComputerSystem; 
    using (ComputerSystem = new ManagementObject(String.Format("Win32_ComputerSystem.Name='{0}'", Environment.MachineName))) 
    { 
     ComputerSystem.Get(); 
     object Result = ComputerSystem["PartOfDomain"]; 
     return (Result != null && (bool)Result); 
    } 
} 
9

Cũng có thể được gọi bằng cách sử dụng system.net

string domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName 

Nếu chuỗi miền trống máy không bị ràng buộc.

1

Nếu vấn đề hiệu suất, sử dụng GetComputerNameEx chức năng:

bool IsComputerInDomain() 
    { 
     uint domainNameCapacity = 512; 
     var domainName = new StringBuilder((int)domainNameCapacity); 
     GetComputerNameEx(COMPUTER_NAME_FORMAT.ComputerNameDnsDomain, domainName, ref domainNameCapacity); 
     return domainName.Length > 0; 
    } 

    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 
    static extern bool GetComputerNameEx(
     COMPUTER_NAME_FORMAT NameType, 
     StringBuilder lpBuffer, 
     ref uint lpnSize); 

    enum COMPUTER_NAME_FORMAT 
    { 
     ComputerNameNetBIOS, 
     ComputerNameDnsHostname, 
     ComputerNameDnsDomain, 
     ComputerNameDnsFullyQualified, 
     ComputerNamePhysicalNetBIOS, 
     ComputerNamePhysicalDnsHostname, 
     ComputerNamePhysicalDnsDomain, 
     ComputerNamePhysicalDnsFullyQualified 
    } 
1

Bạn có thể kiểm tra bằng WMI:

private bool PartOfDomain() 
{ 
    ManagementObject manObject = new ManagementObject(string.Format("Win32_ComputerSystem.Name='{0}'", Environment.MachineName)); 
    return (bool)manObject["PartOfDomain"]; 
} 
Các vấn đề liên quan