My app is running on a computer that is joined to an Active Directory domain. Is there a way to get that domain’s DNS name using WinAPI methods? I want something that will work even if there are no DNS servers or Domain Controllers available.
Right now, the only way I can find is through the Domain property of the Win32_ComputerSystem WMI class:
using System.Management;
public class WMIUtility
{
public static ManagementScope GetDefaultScope(string computerName)
{
ConnectionOptions connectionOptions = new ConnectionOptions();
connectionOptions.Authentication = AuthenticationLevel.PacketPrivacy;
connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
string path = string.Format("\\\\{0}\\root\\cimv2", computerName);
return new ManagementScope(path, connectionOptions);
}
public static ManagementObject GetComputerSystem(string computerName)
{
string path = string.Format("Win32_ComputerSystem.Name='{0}'", computerName);
return new ManagementObject(
GetDefaultScope(computerName),
new ManagementPath(path),
new ObjectGetOptions()
);
}
public static string GetDNSDomainName(string computerName)
{
using (ManagementObject computerSystem = GetComputerSystem(computerName))
{
object isInDomain = computerSystem.Properties["PartOfDomain"].Value;
if (isInDomain == null) return null;
if(!(bool)isInDomain) return null;
return computerSystem.Properties["Domain"].Value.ToString();
}
}
}
The only thing I can find in WinAPI is the NetGetJoinInformation method, which returns the NetBIOS domain name:
using System.Runtime.InteropServices;
public class PInvoke
{
public const int NERR_SUCCESS = 0;
public enum NETSETUP_JOIN_STATUS
{
NetSetupUnknownStatus = 0,
NetSetupUnjoined,
NetSetupWorkgroupName,
NetSetupDomainName
}
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
protected static extern int NetGetJoinInformation(string lpServer, out IntPtr lpNameBuffer, out NETSETUP_JOIN_STATUS BufferType);
[DllImport("netapi32.dll", SetLastError = true)]
protected static extern int NetApiBufferFree(IntPtr Buffer);
public static NETSETUP_JOIN_STATUS GetComputerJoinInfo(string computerName, out string name)
{
IntPtr pBuffer;
NETSETUP_JOIN_STATUS type;
int lastError = NetGetJoinInformation(computerName, out pBuffer, out type);
if(lastError != NERR_SUCCESS)
{
throw new System.ComponentModel.Win32Exception(lastError);
}
try
{
if(pBuffer == IntPtr.Zero)
{
name = null;
}
else
{
switch(type)
{
case NETSETUP_JOIN_STATUS.NetSetupUnknownStatus:
case NETSETUP_JOIN_STATUS.NetSetupUnjoined:
{
name = null;
break;
}
default:
{
name = Marshal.PtrToStringUni(pBuffer);
break;
}
}
}
return type;
}
finally
{
if(pBuffer != IntPtr.Zero)
{
NetApiBufferFree(pBuffer);
}
}
}
}
I think what you are looking for is
GetComputerNameExwithComputerNameDnsDomainas first parameter. But it’s possible that you want one of the other types there. Still,GetComputerNameExis the function you are looking for from how I understand the question.PInvoke details here.
You raise a fair point in your comment, so sure, in this case
LsaQueryInformationPolicywithPolicyDnsDomainInformationmay be the better way to get the DNS name of the domain of which the computer is a member.But it is a special case and your question didn’t mention any such special cases. This should only ever be the case when the primary DNS suffix has been set and differs from the DNS domain name of which the machine is a member. For all practical purposes
GetComputerNameExwill do exactly what you want.