Retrieving a users fullname from their domain account (No Interop required)

Published Tuesday, May 25, 2004 11:11 PM

In a current project, there was a requirement to have a web site that used windows integrated authentication, so that valid users who have logged onto the domain would not have to authenticate themselves to gain access to the site. Pretty standard stuff. We also had a requirement to extract the users first and last name from the domain and use that to populate information on the page.

I am sure it has been done many times before but I thought I would post the utility code I developed to first query for a users domain, then use that to extract the users fullname from their domain account information and separate into their first name and last name. It uses the System.Management namespace exclusively and ofcourse WMI to perform its magic. In our scenario, the web site had impersonation enabled, and in the code we simply called the

WMIQueryResults results = QueryCurrentDomainUser(true);
string fullName = String.Format(“{0} {1}“,results.UserFirstName,results.UserLastName);

function. The 'true' parameter indicates to retrieve the users full name. This obviously takes extra time to execute due to the network queries that must be performed against the domain controller.

Simply copy and paste the code below into a .cs file, and you are away. Note that it returns the results in a class structure of WMIQueryResults and by default, expects the domain users full name to be in lastname, firstname order, although this can be changed easily enough.

Hope you find it useful.

****************Copy and Paste the code Below********************

using System;
using System.Management;


namespace Util.WMI
{
 #region WMIQueryResults Return Result class
 /// <summary>
 /// Class to hold the results of the WMI Query
 /// </summary>
 public class WMIQueryResults
 {
  #region Private Variables

  private string m_FullyQualifiedUserName = null;
  private string m_DefaultDomainController = null;
  private string m_DomainName = null;
  private string m_UserName = null;
  private string m_FullName = null;
  private string m_userFirstName = null;
  private string m_userLastName = null;

  #endregion

  #region Public Properties

  /// <summary>
  /// Fully Qualified User Name. Typically in the format of DOMAIN\UserName
  /// </summary>
  public string FullyQualifiedUserName
  {
   get { return m_FullyQualifiedUserName; }
   set { m_FullyQualifiedUserName = value; }
  }

  /// <summary>
  /// Default Domain controller. This does not necessarily represent the default domain and will typically represent the
  /// machine name that is the PDC (primary domain controller)
  /// </summary>
  public string DefaultDomainController
  {
   get { return m_DefaultDomainController; }
   set { m_DefaultDomainController = value; }
  }

  /// <summary>
  /// The Domain Name of the current user. If the fully qualified user name contains a domain identifier, then this is
  /// stripped out and returned, otherwise the domain controller is returned.
  /// </summary>
  public string DomainName
  {
   get { return m_DomainName; }
   set { m_DomainName = value; }
  }

  /// <summary>
  /// The username portion only. This is username part of the fully qualified user name minus the domain identifier.
  /// </summary>
  public string Username
  {
   get { return m_UserName; }
   set { m_UserName = value; }
  }

  /// <summary>
  /// This is the users full name as gathered from the WinNT/Active directory database/controller.
  /// </summary>
  public string UserFullName
  {
   get { return m_FullName; }
   set { m_FullName = value; }
  }

  /// <summary>
  /// The Firstname of the user, extracted from the users full name. If no full name was retrieved or found, then this
  /// property will be blank (Empty string)
  /// </summary>
  public string UserFirstName
  {
   get { return m_userFirstName; }
   set { m_userFirstName = value; }
  }

  /// <summary>
  /// The Lastname of the user, extracted from the users full name. If no full name was retrieved or found, then this
  /// property will contain the username.
  /// </summary>
  public string UserLastName
  {
   get { return m_userLastName; }
   set { m_userLastName = value; }
  }
  #endregion
 }
 #endregion

 #region UserFullNameFormat Enumeration
 /// <summary>
 /// This enumeration represents what format the domain holds the current users full name. If the domain lists the users
 /// name as "LastName, FirstName", then setting that via the 'LastName_FirstName' enumeration causes the WMI utility
 /// class to recognise which is the first name and which is the last name. An incorrect setting will simply mean that the
 /// WMI utility class will identify the users last name as their first name.
 /// </summary>
 /// <remarks>The default value for the WMIDomainNameUtility class that uses this enumeration is "LastName_FirstName"</remarks>
 public enum UserFullNameFormat
 {
  LastName_FirstName,
  FirstName_LastName
 }
 #endregion

 /// <summary>
 /// This class handles the querying of a users domain, username, and full name as described by the domain. This
 /// information is gathered using WMI (Windows Management Instrumentation) and may take time to execute given that it
 /// needs to query the domain controller over the netork for these pieces of information.
 /// </summary>
 /// <remarks>The default naming format expected from this class is that the users fullname is in "LastName, FirstName" format.
 /// You can change the format to "FirstName, LastName" by supplying a ne enumeration value in the constructor. Also, this class
 /// will strip out any comma's or semi-colons it finds in the name and assumes the names are separated by a space.</remarks>
 public class WMIDomainUser
 {
  #region Private Variables
  private UserFullNameFormat m_nameFormat = UserFullNameFormat.LastName_FirstName;
  #endregion

  #region Constructors
  public WMIDomainUser()
  {
  }

  public WMIDomainUser(UserFullNameFormat fullNameFormat) : this()
  {
   m_nameFormat = fullNameFormat;
  }
  #endregion

  #region QueryCurrentDomainUser Method
  public WMIQueryResults QueryCurrentDomainUser(bool retrieveFullName)
  {

   WMIQueryResults results = new WMIQueryResults();

   try
   {
    ManagementObjectSearcher srchr = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystem");
    ManagementObjectCollection coll = srchr.Get();
    foreach (ManagementObject mo in srchr.Get())
    {
     results.FullyQualifiedUserName = (string)mo["UserName"];
     results.DefaultDomainController = (string)mo["Domain"];
     SplitDomainAndUserName(results);
     break;  // We only want the first one.
    }

    if (retrieveFullName)
    {
     ManagementScope msc = new ManagementScope( "root\\cimv2" );
     string queryString = String.Format("SELECT * FROM Win32_UserAccount WHERE Domain=\"{0}\" and Name=\"{1}\"",results.DomainName,results.Username);

     SelectQuery q = new SelectQuery(queryString);
     ManagementObjectSearcher query = new ManagementObjectSearcher(msc, q);
     foreach (ManagementObject mo in query.Get())
     {
      results.UserFullName = (string)mo["Fullname"];
      break;  // Only want the first one.
     }
    }

    SplitFirstAndLastName(results);
   }
   catch
   {
    results.UserFullName = "";
    results.Username = "";
    results.DomainName = "";
    results.DefaultDomainController = "";
   }

   return results;
  }
  #endregion

  #region SplitDomainAndUserName
  private void SplitDomainAndUserName(WMIQueryResults currentQueryResults)
  {
   int slashPos = currentQueryResults.FullyQualifiedUserName.IndexOf("\\");
   if ( slashPos > 0 && currentQueryResults.FullyQualifiedUserName.Length > 0)
   {
    string domain = currentQueryResults.FullyQualifiedUserName.Substring(0,slashPos);
    string user = currentQueryResults.FullyQualifiedUserName.Substring(slashPos+1,currentQueryResults.FullyQualifiedUserName.Length-slashPos-1);
    currentQueryResults.DomainName = domain;
    currentQueryResults.Username = user;
   }
   else
   {
    currentQueryResults.Username = currentQueryResults.FullyQualifiedUserName;
    currentQueryResults.DomainName = currentQueryResults.DefaultDomainController;
   }
  }
  #endregion

  #region SplitFirstAndLastName
  private void SplitFirstAndLastName(WMIQueryResults currentQueryResults)
  {
   // These name separators get stripped out
   char[] separators = new char[] {',',';'};

   // We assume that the first and last names (in whatever order), are separated by a space
   System.Text.StringBuilder sb = new System.Text.StringBuilder();
   for (int i = 0; i < currentQueryResults.UserFullName.Length; i++)
   {
    if (Array.IndexOf(separators,currentQueryResults.UserFullName[i]) == -1) // char not found, so add it in.
     sb.Append(currentQueryResults.UserFullName[i]);
   }
   string strippedName = sb.ToString();
   int spacePos = strippedName.IndexOf(" ");
   if (spacePos >= 0)
   {
    string name1 = strippedName.Substring(0,spacePos);
    string name2 = strippedName.Substring(spacePos+1,strippedName.Length-spacePos-1);
    if (m_nameFormat == UserFullNameFormat.LastName_FirstName)
    {
     currentQueryResults.UserFirstName = name2;
     currentQueryResults.UserLastName = name1;
    }
    else
    {
     currentQueryResults.UserFirstName = name1;
     currentQueryResults.UserLastName = name2;
    }
   }
   else
   {
    currentQueryResults.UserFirstName = "";
    currentQueryResults.UserLastName = currentQueryResults.UserFullName;
   }
  }
  #endregion
 }
}

by Glav

Comments

# Brian Desmond said on Sunday, May 30, 2004 1:20 PM

You're kidding? This task is what System.DirectoryServices is designed to do...

# Paul Glavich said on Sunday, May 30, 2004 8:42 PM

This is not for ActiveDirectory though. The current environment is a traditional NT4 domain.

Does that still qualify for your stamp of dis-approval?

# Paul Glavich said on Sunday, May 30, 2004 9:54 PM

I should also qualify that by saying I did try using methods from that namespace, however I run into errors saying something along the lines of "Unable to query" or "This resource does not support querying" or some such error. I assumed the admins had disabled any features (if available under the current environment - as it maybe a mix...I am not 100% sure..its quite large) and the scope of the project that used this code did not justify being able to diagnose and rectify at the domain level, hence the code you see above, which did work.

Leave a Comment

(required) 
(required) 
(optional)
(required) 

This Blog

Syndication