6

We have a domain with full name, e.g. long-domainname.com; this domain name is replaced with alias short. this alias can be retrieved using netapi32.dll, like this:

[DllImport("Netapi32.dll")]
static extern int NetApiBufferFree(IntPtr Buffer);

// Returns the domain name the computer is joined to, or "" if not joined.
public static string GetJoinedDomain()
{
    int result = 0;
    string domain = null;
    IntPtr pDomain = IntPtr.Zero;
    NetJoinStatus status = NetJoinStatus.NetSetupUnknownStatus;
    try
    {
        result = NetGetJoinInformation(null, out pDomain, out status);
        if (result == ErrorSuccess &&
            status == NetJoinStatus.NetSetupDomainName)
        {
            domain = Marshal.PtrToStringAuto(pDomain);
        }
    }
    finally
    {
        if (pDomain != IntPtr.Zero) NetApiBufferFree(pDomain);
    }
    if (domain == null) domain = "";
    return domain;
}

This method return the sort value. But using the System.DirectoryServices.ActiveDirectory.Domain class, and its Name property, I get long-domainname.com value. Searching the properties under the Debug mode, I couldn't find any short value field or property. Is it possible with System.DirectoryServices.ActiveDirectory.Domain class? Or may be it is possible with some other class of System.DirectoryServices namespace? How to get the short domain name value without importing external *.dll?

stukselbax
  • 5,855
  • 3
  • 32
  • 54

2 Answers2

9
private string GetNetbiosDomainName(string dnsDomainName)
    {
        string netbiosDomainName = string.Empty;

        DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");

        string configurationNamingContext = rootDSE.Properties["configurationNamingContext"][0].ToString();

        DirectoryEntry searchRoot = new DirectoryEntry("LDAP://cn=Partitions," + configurationNamingContext);

        DirectorySearcher searcher = new DirectorySearcher(searchRoot);
        searcher.SearchScope = SearchScope.OneLevel;
        searcher.PropertiesToLoad.Add("netbiosname");
        searcher.Filter = string.Format("(&(objectcategory=Crossref)(dnsRoot={0})(netBIOSName=*))", dnsDomainName);

        SearchResult result = searcher.FindOne();

        if (result != null)
        {
            netbiosDomainName = result.Properties["netbiosname"][0].ToString();
        }

        return netbiosDomainName;
    }
MethodMan
  • 18,625
  • 6
  • 34
  • 52
  • 2
    I upvoted this, because I find it very usefull. I changed the DirectoryEntry line to: DirectoryEntry rootDSE = new DirectoryEntry(string.Format("LDAP://{0}/RootDSE",dnsDomainName)); That way you can get the NETBIOS Domain name of domains in other (trusted) forests. – Daro Jan 02 '13 at 08:47
  • Daro it's all good we are all here to help one another as well as learn from one another.. you're welcome – MethodMan Jan 02 '13 at 10:27
0

The accepted answer works, but has two issues that can be addressed:

  1. It only works if the credentials you run it under is an account in the same forest as the domain you're looking at, and
  2. It requires two network requests.

Here is a method that does it in one network request:

private string GetNetbiosDomainName(string dnsDomainName) {
    var domain = new DirectoryEntry($"LDAP://{dnsDomainName}"); //bind to the root of the domain
    domain.RefreshCache(new [] { "msDs-PrincipalName" });
    
    return ((string)domain.Properties["msDs-PrincipalName"].Value).Trim('\\');
}

It does require that the account you run this with is trusted by the domain you're looking up (not necessarily in the same forest), but you can avoid even that by passing credentials in the constructor of DirectoryEntry.

Gabriel Luci
  • 38,328
  • 4
  • 55
  • 84