Getting a machine’s NetBIOS domain name in C#

I tried to find some mechanism to get the current machine’s NetBIOS domain name (the machine domain, not user domain), but couldn’t find anything in the usual places (e.g. System.Environment). If you want the fancy-schmancy Active Directory DNS domain then you can use Domain.GetComputerDomain().Name from System.DirectoryServices.ActiveDirectory, or another one that I stumbled across in Reflector was IPGlobalProperties.GetIPGlobalProperties().DomainName that lives in System.Net.NetworkInformation. But a simple way of getting the old-skool NetBIOS/LanManager-style machine domain name proved elusive.

Some googling suggested that WMI would provide the answer but I find WMI a little heavyweight, and not always reliable. The information is also probably in the registry somewhere, although I couldn’t find it after a cursory scan. The proper, supported way it would appear is to use the Network Management API. So my solution entailed P/Invoking to netapi32.dll.

If you’re after the same information I hope you find the code below useful. Once you’ve incorporated this in your project, just call the GetMachineNetBiosDomain method. It will return the machine’s Workgroup name if the machine is not domain-joined.

UPDATE: Now works on 64-bit thanks to update sent by Rp Brongers.

using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

class NetUtil
{
    [DllImport("netapi32.dll", CharSet = CharSet.Auto)]
    static extern int NetWkstaGetInfo(string server,
        int level,
        out IntPtr info);

    [DllImport("netapi32.dll")]
    static extern int NetApiBufferFree(IntPtr pBuf);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    class WKSTA_INFO_100
    {
        public int wki100_platform_id;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string wki100_computername;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string wki100_langroup;
        public int wki100_ver_major;
        public int wki100_ver_minor;
    }

    public static string GetMachineNetBiosDomain()
    {
        IntPtr pBuffer = IntPtr.Zero;

        WKSTA_INFO_100 info;
        int retval = NetWkstaGetInfo(null, 100, out pBuffer);
        if (retval != 0)
            throw new Win32Exception(retval);

        info = (WKSTA_INFO_100)Marshal.PtrToStructure(pBuffer, typeof(WKSTA_INFO_100));
        string domainName = info.wki100_langroup;
        NetApiBufferFree(pBuffer);
        return domainName;
    }
}

22 Responses to Getting a machine’s NetBIOS domain name in C#

  1. Raj says:

    The given method worked for me. Thanks for the help

  2. JayThree says:

    Was just looking for this.. thanks broham.

  3. nomex says:

    Thanks, I was looking for this!

  4. Edward Wilde says:

    Hey great post, thanks. Just wanted to let you know that I found a way of looking up the netbios name using DirectoryServices or System.Environment

    Thanks Ed.

    • Duncan Smart says:

      Edward – that’s interesting, although I note it requires a query to Active Directory, so won’t work if run on say, a laptop that’s not currently connected to the corporate network.

  5. Bob Vila says:

    this code is orgasmic exactly what i need

  6. Pingback: Lookup the Netbios name of a domain using directory services « Edward Wilde

  7. Rp Brongers says:

    Thank you for this example, it works like a charm on 32 bits platforms. However, on Windows 7 64bits I ran into a problem, which I also fixed. Maybe you would be so kind to update the post with the fix to make it work on 64 bits as well (see below).
    On a 64bit platform, structures should not be passes to the netapi call directly (or any native dll for that matter). Instead, use an IntPtr and map the result to your structure.
    (Note: this was tested on a machine running Windows 7 64bit)

    [DllImport("netapi32.dll", CharSet = CharSet.Auto)]
    static extern int NetWkstaGetInfo([MarshalAs(UnmanagedType.LPWStr)]string server,
    int level,
    out IntPtr info);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    class WKSTA_INFO_100
    {
    public int wki100_platform_id;
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
    public string wki100_computername;
    [MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
    public string wki100_langroup;
    public int wki100_ver_major;
    public int wki100_ver_minor;
    }

    public static string GetMachineNetBiosDomain()
    {
    IntPtr buffer = new IntPtr();

    WKSTA_INFO_100 info;
    int retval = NetWkstaGetInfo(null, 100, out buffer);
    if (retval != 0)
    throw new Win32Exception(retval);

    Int32 pointer = buffer.ToInt32();
    info = (WKSTA_INFO_100)Marshal.PtrToStructure(
    new IntPtr(pointer), typeof(WKSTA_INFO_100));
    string domainName = info.wki100_langroup;
    NetApiBufferFree(buffer);
    return domainName;
    }

  8. Geert says:

    I’m currently testing this snippet converted to vb.net
    I couldn’t understand from the sample and comments:

    Is “Int32 pointer = buffer.ToInt32();” needed on 64 bit or not? (which is the correct function)

    Thanks for the code.

  9. HELLO says:

    Output the FQDN of a specified server NetBIOS name. Then you can query the substring from the FQDN.

    IPHostEntry he = Dns.GetHostEntry(serverNetBIOSName);
    IPHostEntry he2 = Dns.GetHostEntry(he.AddressList[0]);
    Console.WriteLine(he2.HostName);

  10. Geert says:

    “Output the FQDN of a specified server NetBIOS name. Then you can query the substring from the FQDN.” -> don’t do this, it is not always correct.
    The netbios name can be different from the dns name

  11. GL says:

    Thank you for code. I tried all “official” .Net approaches but seems to be Win(32)API will live long life.

  12. oleg_m says:

    Thank you for code. But this code not working, when running as a service (by LocalSystem). Any ideas?

  13. oleg_m says:

    NetWkstaGetInfo Function…
    If the function fails, the return value can be one of the following error codes.

    ERROR_ACCESS_DENIED The user does not have access to the requested information.

    32 int retval = NetWkstaGetInfo(null, 100, out pBuffer);
    33 if (retval != 0)
    34 throw new Win32Exception(retval);

  14. oleg_m says:

    >Is this code running on a Domain Controller?
    No. Windows Server 2003 Standard Edition, but no domain controller.

    >There’s some info about this in the docs
    > that might be relevant
    I read it, before write to you

    I think the reason is localsystem-user: he has no right to work in a network.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>