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; } }
The given method worked for me. Thanks for the help
Was just looking for this.. thanks broham.
Thanks, I was looking for this!
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.
Which can be found: http://blogs.edwardwilde.com/2009/12/14/lookup-the-netbios-name-of-a-domain-using-directory-services/
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.
this code is orgasmic exactly what i need
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;
}
Done it, thanks! Just removed (what I thought was) an unnecessary conversion to and from Int32.
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.
@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.
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);
“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
Thank you for code. I tried all “official” .Net approaches but seems to be Win(32)API will live long life.
Thank you for code. But this code not working, when running as a service (by LocalSystem). Any ideas?
Odd – is any exception thrown?
Win32Exception: System.ComponentModel.Win32Exception: Access is denied
Is this code running on a Domain Controller? There’s some info about this in the docs that might be relevant http://msdn.microsoft.com/en-us/library/aa370663.aspx
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);
>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.
OK, I guess there must be something missing from LocalSystem’s access token that these API calls specifically check for. I would think that if you ran the service as a specific user it would then work OK. Or maybe one of the other built-in accounts: http://msdn.microsoft.com/en-us/library/ms686005(VS.85).aspx
Is there any service on the target computer needed to run in order to let this work? i couldn’t find that info on Msdn.
Not as far as I know. Is the code not working for you?
Just curious 🙂 For WMI for example you need to have the WMI service running, why actually use that if this always works. And WMI seems the newer tech.
WMI does a bunch of things, many of which are just wrappers around existing mechanisms such as this one. I always prefer the simplest possible thing that will work.
Hi Duncan, is there any way we can Disable the NetBios programmatically? I’m thinking to expend your code & see if I can get it work.
Duncan, I found this :
http://msdn.microsoft.com/en-us/library/windows/desktop/aa393601(v=vs.85).aspx
How do I get it work?
You’d be better off just writing a script. See http://msdn.microsoft.com/en-us/library/windows/desktop/aa394595(v=vs.85).aspx for examples and adjust to call SetTcpipNetbios.