如何确定我正在使用的计算机是否为域控制器?

3

使用C#,如何判断我的代码运行的计算机是否为域控制器。

我不想“出去”收集有关域中其他域控制器的信息……我只关心我的代码运行的机器是否是域控制器。此外,我不需要知道它是否是主域控制器……只需要知道它是否是域控制器。

以下是我尝试过的方法:

尝试1:

    private bool IsDomainController()
    {
        Domain domain = Domain.GetCurrentDomain();
        string domainName = domain.ToString();
        bool bIsDC = false;
        DirectoryContext ctx = new DirectoryContext(DirectoryContextType.Domain, domainName);

        try
        {
            using (DomainController dc = DomainController.FindOne(ctx, LocatorOptions.ForceRediscovery))
            {
                bIsDC = true;
            }
        }
        catch (Exception)
        {
            bIsDC = false;              
        }

        return bIsDC;
    }

and

TRIAL 2

    public bool IsThisMachineIsADomainController()
    {
        Domain domain = Domain.GetCurrentDomain();

        string thisMachine = String.Format("{0}.{1}", Environment.MachineName, domain.ToString());
        thisMachine = thisMachine.ToLower();

        //Enumerate Domain Controllers
        List<string> allDcs = new List<string>();

        string name = "";
        foreach (DomainController dc in domain.DomainControllers)
        {
            name = dc.Name.ToLower();
            allDcs.Add(name);
        }
        return allDcs.Contains(thisMachine);
    }

这两个选项都合适吗?为什么合适或不合适?

2
你最初尝试的代码在哪里? - Cubicle.Jockey
我刚刚发布了我拥有的代码。 - MrLister
4
它们工作成功吗?如果是的话,那么最好尝试http://codereview.stackexchange.com/,因为SO不是"What is the best"问题的最佳场所。 - Eugene Podskal
谢谢您的配合,现在其他人可以更好地帮助您了。 - Cubicle.Jockey
你也可以潜在地使用注册表作为快速解决方案,但你必须找到键。在2008年,它们在这里:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerManager,而似乎在2012年它们在这里:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerManager\ServicingStorage\ServerComponentCache - xDaevax
Eugene Podskal - 他们能够工作,但我们的关注点是找到一种方法来--仅--测试代码运行的机器 - 这两种方法都会命中附加的控制器的整个域并返回信息...这可能需要几分钟... :-( - MrLister
3个回答

2

在进行了大量的研究后,发现有两种方法:

适用于 Windows 2008 服务器的方法:

    public bool isActiveDirectoryDomainServicesInstalled()
    {
        bool bRetval = false;
        try
        {
            uint uID = 110;
            string search = string.Format("SELECT * FROM Win32_ServerFeature WHERE ID = {0}", uID);
            ManagementObjectSearcher oSearcher = new ManagementObjectSearcher("root\\CIMV2", search);

            foreach (var oReturn in oSearcher.Get())
            {
                if ((uint)(oReturn["ID"]) == uID)
                {
                    bRetval = true;
                    break;
                }
            }
        }
        catch (Exception)
        {
            bRetval = false;
        }

        return bRetval;
    }

适用于 Windows 2008 和 Windows 2012 服务器

public bool IsThisMachineIsADomainController()
{
    Domain domain = Domain.GetCurrentDomain();

    string thisMachine = String.Format("{0}.{1}", Environment.MachineName, domain.ToString());
    thisMachine = thisMachine.ToLower();

    //Enumerate Domain Controllers
    List<string> allDcs = new List<string>();

    string name = "";
    foreach (DomainController dc in domain.DomainControllers)
    {
        name = dc.Name.ToLower();
        allDcs.Add(name);
    }
    return allDcs.Contains(thisMachine);
}

不要使用 Environment.MachineName 来获取主机名!!这是 NetBIOS 名称,最长为 15 个字符。你需要获取主机名。使用以下代码:System.Net.Dns.GetHostName().Split('.')[0]; - marsh-wiggle

0

您可以使用http://msdn.microsoft.com/en-us/library/y9w58cz1(v=vs.110).aspx来获取一个可用于您的站点的DomainControllerCollection

那就是一组DomainController对象。

最后将它们的IP地址与您本地的IP设置进行比较。

Domain d = Domain.GetCurrentDomain();
DomainControllerCollection dcc = d.FindAllDiscoverableDomainControllers("domain.local");
IPAddress[] localIPs = Dns.GetHostAddresses(Dns.GetHostName());
Boolean scanDone = false;
foreach (DomainController dc in dcc)
{
    foreach (IPAddress localip in localIPs)
    {
        if (dc.IPAddress.ToString().Equals(localip.ToString()))
        {
            MessageBox.Show("Woop Woop! I'm a DC!");
            scanDone = true;
            break;
        }
    }

    if (scanDone) break;
}

您需要将 System.DirectoryServices 引用添加到您的项目中。


这段代码和我的“TRIAL 2”代码的主要区别是什么?我认为你的代码更“昂贵”,因为执行了多个IP查找,而在“TRIAL 2”代码中,只比较了合格的域控制器名称 - 你有什么想法? - MrLister

-1

尝试使用这个Win32 API:NetServerEnum(),它“列出了在域中可见的指定类型的所有服务器。”

您的其他选择是使用LDAP/Active Directory查询来枚举域控制器:我认为您可能会发现P/Invoke更容易和更受欢迎。

如果您想尝试LDAP路线,我建议阅读Joe Kaplan和Ryand Dunn的The .NET Developer's Guide to Directory Services Programming

Cover: The .Net Developer's Guide to Directory Services Programming


我不想使用Interop...只用C#。 - MrLister
@user3174075:请看我修改后的答案,另有建议。 - Nicholas Carey
此外,根据NetServerEnum中的注释,看起来这个函数在我们所针对的操作系统上存在一些错误。 - MrLister
查看NetServerEnum文档,我看到了两个标志:SV_TYPE_DOMAIN_CTRL和SV_TYPE_DOMAIN_BAKCTRL...我不知道我正在运行的计算机是主控制器还是域备份控制器...此外...这两者之间有什么区别? - MrLister
另外需要注意的是:NetServerEnum 要求 Broswer 服务已安装并运行... 我们不想为我们的应用程序添加另一个依赖服务...(谁会呢?)因此,NetServerEnum 已经被排除在外。 - MrLister

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接