CodeGo.net>如何检测机器是否加入域?

如何检测计算机是否已加入Active Directory域(相对于工作组模式)?

DSO asked 2019-11-07T10:14:16Z
12个解决方案
92 votes

如果不需要,不要傻傻地用pinvoke。

引用System.DirectoryServices,然后调用:

System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain()

如果计算机未加入域,则抛出ActiveDirectoryObjectNotFoundException。返回的Domain对象包含您要查找的Name属性。

Joe Clancy answered 2019-11-07T10:15:22Z
28 votes

您可以PInvoke到诸如NetGetDcName的Win32 API,它将为未加入域的计算机返回null / empty字符串。

甚至更好的是NetGetJoinInformation,它将在工作组或域中明确告诉您计算机是否未连接。

我使用NetGetJoinInformation将其组合在一起,这对我有用:

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
    }

}
Rob answered 2019-11-07T10:14:42Z
21 votes

也可以通过使用system.net来调用

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

如果域字符串为空,则表示机器未绑定。

返回的属性文档[https://docs.microsoft.com/zh-cn/dotnet/api/system.net.networkinformation.ipglobalproperties.domainname?view=netframework-4.7.2#System_Net_NetworkInformation_IPGlobalProperties_DomainName]

Eric Herlitz answered 2019-11-07T10:16:03Z
7 votes
ManagementObject cs;
        using(cs = new ManagementObject("Win32_ComputerSystem.Name='" + System.Environment.MachineName + "'" ))
        {
            cs.Get();
            Console.WriteLine("{0}",cs["domain"].ToString());
        }

那应该允许您获得域。 我相信如果您属于工作组而不是域,则它将为null或为空。

确保引用System.Management

Stephan answered 2019-11-07T10:16:34Z
5 votes

只是想在VB中删除Rob的代码:

 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

以及Stephan的代码在这里:

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


我相信,即使当前用户不是域成员,也只有第二个代码可以让您知道计算机加入的域。

PatTheFrog answered 2019-11-07T10:17:14Z
4 votes

环境变量可以为您工作。

Environment.UserDomainName

有关更多详细信息,请参见MSDN Link。

Environment.GetEnvironmentVariable("USERDNSDOMAIN")

我不确定此环境变量是否存在于域中。

如果我错了Windows Admin怪胎,请纠正我-我相信一台计算机可以位于多个域中,因此了解您所在的域(如果有)而不是任何域可能更为重要。

Austin Salonen answered 2019-11-07T10:18:05Z
4 votes

您可以检查Win32_ComputerSystem WMI类的PartOfDomain属性。MSDN说:

域名

数据类型:布尔值

访问类型:只读

如果为True,则计算机是域的一部分。 如果值为NULL,则计算机不在域中或状态未知。 如果你   从域中取消加入计算机,该值将变为false。

/// <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);
    }
}   
neilbgr answered 2019-11-07T10:18:59Z
3 votes

这是我基于异常处理/注释的方法,这些方法是根据本文中的一些答案开发的。

  1. 获取计算机连接到的域。
  2. 仅当用户实际登录到域帐户时,才返回域名。

    /// <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;
    }
    
blak3r answered 2019-11-07T10:19:47Z
1 votes

如果性能很重要,请使用GetComputerNameEx函数:

    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
    }
Artem answered 2019-11-07T10:20:12Z
1 votes

您可能想尝试使用DomainRole WMI字段。 值0和2分别表示独立工作站和独立服务器。

我们将其用于网络审计软件的XIA Configuration,因此我在这里介绍了该方法...

/// <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);
    }
}
David Homer answered 2019-11-07T10:20:46Z
1 votes

您可以使用WMI进行检查:

private bool PartOfDomain()
{
    ManagementObject manObject = new ManagementObject(string.Format("Win32_ComputerSystem.Name='{0}'", Environment.MachineName));
    return (bool)manObject["PartOfDomain"];
}
Me Hungry answered 2019-11-07T10:21:15Z
0 votes

如果本地用户登录,则上述提议的解决方案在域计算机上返回false。

我发现的最可靠的方法是通过WMI:

[http://msdn.microsoft.com/zh-cn/library/aa394102(v = vs.85).aspx](请参阅domainrole)

Andrew Morgan answered 2019-11-07T10:22:00Z
translate from https://stackoverflow.com:/questions/926227/how-to-detect-if-machine-is-joined-to-domain