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

14 comments so far

  1. Raj on

    The given method worked for me. Thanks for the help

  2. JayThree on

    Was just looking for this.. thanks broham.

  3. nomex on

    Thanks, I was looking for this!

  4. Edward Wilde on

    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 on

      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 on

    this code is orgasmic exactly what i need

  6. Rp Brongers on

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

    • Duncan Smart on

      Done it, thanks! Just removed (what I thought was) an unnecessary conversion to and from Int32.

  7. Geert on

    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.

    • Duncan Smart on

      @Geert – I incorporated Rp Brongers’ changes already – but also got rid of the ToInt32 bit. Should work on x64 – pretty sure I tested it there.

  8. HELLO on

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

  9. Geert on

    “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


Leave a reply