如何检测机器是否加入域(在C#中)?

DSO*_*DSO 56 .net c#

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

小智 92

如果你不需要,不要吝啬pinvoke.

参考System.DirectoryServices,然后调用:

System.DirectoryServices.ActiveDirectory.Domain.GetComputerDomain()
Run Code Online (Sandbox Code Playgroud)

ActiveDirectoryObjectNotFoundException如果机器未加入域,则抛出一个.返回的Domain对象包含您要查找的Name属性.

  • 别人注意..**请确保使用GetComputerDomain()**(如上所述)和**而不是GetCurrentDomain()**.如果您没有加入域,GetCurrentDomain()会阻塞多年. (10认同)
  • 我总是喜欢发现存在几乎任何东西的托管版本. (3认同)
  • 此调用存在问题,因为在许多配置上大约需要2分钟. (3认同)
  • 如果您需要知道计算机是否已加入域,即使该计算机当前未连接到网络,该解决方案也不起作用。在这种情况下,它将抛出ActiveDirectoryObjectNotFoundException。 (2认同)

Rob*_*Rob 28

您可以PInvoke到Win32 API,例如NetGetDcName,它将为非域加入的机器返回空/空字符串.

更好的是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
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 请务必注意,`NetGetJoinInformation` 返回旧的 NetBIOS 域名,而不是域名(因此 NetGetJoinInformation 中的 ***Net***) (2认同)
  • 而不是 `throw new Exception("Domain Info Get Failed");` 你应该做 `throw new Exception("Domain Info Get Failed", new Win32Exception());` insetad。内部`Win32Exception` 将在内部调用`Marshal.GetLastWin32Error()` 并在内部异常中为该代码设置错误代码和错误消息。这就是为什么你在 p/invoke 签名中执行 `SetLastError=true`,这样 `Marshal.GetLastWin32Error()` 就会起作用。 (2认同)

Eri*_*itz 21

也可以使用system.net调用

string domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName
Run Code Online (Sandbox Code Playgroud)

如果域字符串为空,则不绑定机器.

  • 这是最好的答案,因为它既是托管解决方案,也是最快的解决方案. (3认同)
  • 这将返回计算机的主 DNS 后缀,这并不一定表明它位于 AD 中。如果您将 DNS 后缀添加到工作组中的电脑,则会返回该后缀名称,而不是空字符串。 (2认同)

Ste*_*han 7

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

这应该允许你获得域名.如果您是工作组的一部分而不是域,我相信它将为null或为空.

确保参考System.Management

  • 第二个想法我不认为这会奏效.事实证明,我的测试框的工作组名称实际上是WORKGROUP.我认为它返回工作组名称,而不是固定值,从API角度来看更有意义,但这意味着您无法使用它来确定其域是否已加入. (2认同)

Pat*_*rog 5

只是想在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
Run Code Online (Sandbox Code Playgroud)

和斯蒂芬的代码一样:

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
Run Code Online (Sandbox Code Playgroud)


我相信只有第二个代码才能让您知道机器加入了哪个域,即使当前用户不是域成员.