3

Using C#, what is the way to find out if the machine my code is running on IS a domain controller.

I do not want to "go out" and collect information about any other domain controllers on the domain... I am ONLY interested if the machine machine my code is running on IS a domain controller or not. Additionally, I do not need to know if its a primary domain controller ... just if it IS a domain controller.

Here is what I have tried

TRIAL 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);
    }

Are either of these suitable and why or why not?

MrLister
  • 634
  • 7
  • 32
  • 2
    Where is the code you have tried first? – Cubicle.Jockey Aug 28 '14 at 18:23
  • just posted up the code that I have – MrLister Aug 28 '14 at 18:26
  • 4
    Do they work successfully? If yes, then you'd better try http://codereview.stackexchange.com/, because SO isn't a best place for the "what is the best" questions. – Eugene Podskal Aug 28 '14 at 18:27
  • Thanks for that, now people can better help you. – Cubicle.Jockey Aug 28 '14 at 18:28
  • You could also potentially use the registry as a quick win, though you'd have to find the Keys. On 2008, they are found here: `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerManager` and it seems like for 2012 they are here: `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ServerManager\ServicingStorage\ServerComponentCache` – xDaevax Aug 28 '14 at 18:43
  • Eugene Podskal - they work, but our concern is to find a way to --only-- test the machine the code is running on - both of these methods hit the entire domain for controllers that are attached and return the information... which may take minutes... :-( – MrLister Aug 29 '14 at 16:05

3 Answers3

2

After much research... there are two ways:

Works on Windows 2008 server:

    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;
    }

. AND .

Works on Windows 2008 and Windows 2012 servers

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);
}
MrLister
  • 634
  • 7
  • 32
  • Don't use `Environment.MachinName` for this!! This is the NetBIOS Name with a max length of 15 characters. You need the hostname. To get it use: `System.Net.Dns.GetHostName().Split('.')[0];` – marsh-wiggle Dec 14 '20 at 17:15
0

You can use http://msdn.microsoft.com/en-us/library/y9w58cz1(v=vs.110).aspx to get a DomainControllerCollection available to your site.

That's a Collection of DomainController Objects then.

Finally compair their ips with your local ip set.

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;
}

You need to add the Reference to System.DirectoryServices to your project.

dognose
  • 20,360
  • 9
  • 61
  • 107
  • What is the primary difference between this code and my "TRIAL 2" code? I think your code is more "costly" as several IP lookups are performed, and in the "TRIAL 2" code, only a qualified domain controller name is compared - your thoughts? – MrLister Aug 29 '14 at 16:02
-1

Try this Win32 API: NetServerEnum(), which "lists all servers of the specified type that are visible in a domain."

Your other options would be to use LDAP/Active Directory queries to enumerate the domain controllers: I would posit that you might find P/Invoke easier and more palatable.

If you want to try the LDAP route, I would suggest The .NET Developer's Guide to Directory Services Programming by Joe Kaplan and Ryand Dunn.

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

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
  • I don't want to user interop ... only c# – MrLister Aug 28 '14 at 18:29
  • @user3174075 interop isn't that hard to add http://www.pinvoke.net/search.aspx?search=NetServerEnum&namespace=[All] – kenny Aug 28 '14 at 18:31
  • @user3174075: see my amended answer for another suggestion. – Nicholas Carey Aug 28 '14 at 18:49
  • Additionally... based on the comments in the NetServerEnum ... it looks like this function has some bugs for the OS we are targeting... ! – MrLister Aug 28 '14 at 18:49
  • Looking over the documentation for NetServerEnum, I see two flags : SV_TYPE_DOMAIN_CTRL and SV_TYPE_DOMAIN_BAKCTRL ... I won't know if the computer I am running on is a primary or a domain backup controller ... additionally... what is the distinction between the two? – MrLister Aug 29 '14 at 16:00
  • another note: NetServerEnum requires that the Broswer service be installed and running... we do not want add yet another dependent service to our app... (who does?) So NetServerEnum is OUT of the running – MrLister Aug 29 '14 at 19:59