Click here to Skip to main content
15,885,104 members
Articles / Programming Languages / C#

Get a User's Full Name

Rate me:
Please Sign up or sign in to vote.
4.61/5 (19 votes)
4 Mar 2013CPOL6 min read 250.5K   69   46
Use .NET 3.5's DirectoryServices namespace to quickly and easily get at a user's full name.

Introduction

The System.DirectoryServices.AccountManagement namespace in .NET 3.5 gives you access to the UserPrincipal class which "Encapsulates principles that are user accounts." There is a .Current property which "Gets a user principal object that represents the current user under which the thread is running." Once you have this UserPrincipal object for the current user, you can get at all kinds of cool properties and methods.

Background 

I wanted to display the current user's full name to see who is using my application and then log that to a table in SQL, how hard could it be!? I was using VB.NET for this particular project so I tried My.User.Name... whew that was pretty easy. Once run, it returned "MyDomain\UsersInitials" since the username standard we have here are the initials. Getting the initials was not very helpful in figuring out who was using my program (I'm too lazy to manually cross reference usernames, with full names in ADUC).

So I had to search around for quite a while and I couldn't find any articles or postings that quickly point to this class for user information. There were other people that had this question and they were turned to everything from using "WinNT://" queries, to using the Win32_UserAccount and the WMI Code Creator, to older articles saying you just can't do it!

Eventually I stumbled upon this article on MSDN.

I figured I'd post an article to maybe make it easier for people to find information on getting at current user properties. 

Using the Code 

Using the code couldn't be easier. Just add a reference and using or imports statement to System.DirectoryServices.AccountManagement and enjoy. 

VB.NET
Imports System.DirectoryServices.AccountManagement

Dim userFullName As String = UserPrincipal.Current.DisplayName

One caveat, as pointed out in a comment below, is that this should be wrapped with a Try...Catch block. If the current user is on a domain and can't reach the domain controller (network failure), he will receive a PrincipalServerDown exception. However if he is not on a domain, he will not receive this error on a network failure.

Also, if you change the username and don't log off, you will receive a NoMatchingPrincipleException since the .Current UserPrincipal name can't be found. This would probably never happen but you might as well Catch it.

If an exception occurs, I'd suggest just using the username from System.Environment.UserName or My.User.Name in VB.

Once you get at the .Current property, which returns a UserPrincipal class, you can access all kinds of properties on the current user. A table of properties is listed below (from here): 

  NameDescription
Public propertyAccountExpirationDateGets or sets a Nullable DateTime that specifies the date and time that the account expires. (Inherited from AuthenticablePrincipal.)
Public propertyAccountLockoutTimeGets the Nullable DateTime that specifies the date and time that the account was locked out. (Inherited from AuthenticablePrincipal.)
Public propertyAdvancedSearchFilterReturns an AdvancedSearchFilter object, for use with Query by Example to set read-only properties before passing the object to the PrincipalSearcher. (Overrides AuthenticablePrincipal..::.AdvancedSearchFilter.)
Public propertyAllowReversiblePasswordEncryptionGets or sets a Boolean value that specifies whether reversible password encryption is enabled for this account. (Inherited from AuthenticablePrincipal.)
Public propertyBadLogonCountGets the number of logon attempts using incorrect credentials for this account. (Inherited from AuthenticablePrincipal.)
Public propertyCertificatesGets a X509Certificate2Collection that contains the X509 certificates for this account. (Inherited from AuthenticablePrincipal.)
Public propertyContextGets a principal context that is associated with the principal. (Inherited from Principal.)
Protected propertyContextRawGets a principal context that is associated with this principal. (Inherited from Principal.)
Public propertyContextTypeGets the context type enumeration value that specifies the type of principal context associated with this principal. (Inherited from Principal.)
Public propertyStatic memberCurrentGets a user principal object that represents the current user under which the thread is running.
Public propertyDelegationPermittedGets or sets a Nullable Boolean value that specifies whether the account may be delegated. (Inherited from AuthenticablePrincipal.)
Public propertyDescriptionGets or sets the description of the principal. (Inherited from Principal.)
Public propertyDisplayNameGets or sets the display name for this principal. (Inherited from Principal.)
Public propertyDistinguishedNameGets the distinguished name (DN) for this principal. (Inherited from Principal.)
Public propertyEmailAddressGets or sets the e-mail address for this account.
Public propertyEmployeeIdGets or sets the employee ID for this user principal.
Public propertyEnabledGets or sets a Nullable Boolean value that specifies whether this account is enabled for authentication. (Inherited from AuthenticablePrincipal.)
Public propertyGivenNameGets or sets the given name for the user principal.
Public propertyGuidGets the GUID associated with this principal. (Inherited from Principal.)
Public propertyHomeDirectoryGets or sets the home directory for this account. (Inherited from AuthenticablePrincipal.)
Public propertyHomeDriveGets or sets the home drive for this account. (Inherited from AuthenticablePrincipal.)
Public propertyLastBadPasswordAttemptGets the Nullable DateTime that specifies the date and time of the last incorrect password attempt on this account. (Inherited from AuthenticablePrincipal.)
Public propertyLastLogonGets the Nullable DateTime that specifies the date and time of the last logon for this account. (Inherited from AuthenticablePrincipal.)
Public propertyLastPasswordSetGets the Nullable DateTime that specifies the last date and time that the password was set for this account. (Inherited from AuthenticablePrincipal.)
Public propertyMiddleNameGets or sets the middle name for the user principal.
Public propertyNameGets or sets the name of this principal. (Inherited from Principal.)
Public propertyPasswordNeverExpiresGets or sets a Boolean value that specifies whether the password expires for this account. (Inherited from AuthenticablePrincipal.)
Public propertyPasswordNotRequiredGets or sets a Boolean value that specifies whether a password is required for this account. (Inherited from AuthenticablePrincipal.)
Public propertyPermittedLogonTimesGets or sets the times when the principal can logon. (Inherited from AuthenticablePrincipal.)
Public propertyPermittedWorkstationsGets the list of workstations that this principal is permitted to log into. (Inherited from AuthenticablePrincipal.)
Public propertySamAccountNameGets or sets the SAM account name for this principal. (Inherited from Principal.)
Public propertyScriptPathGets or sets the script path for this account. (Inherited from AuthenticablePrincipal.)
Public propertySidGets the Security ID (SID) of the principal. (Inherited from Principal.)
Public propertySmartcardLogonRequiredGets or sets a Boolean value that specifies whether a smartcard is required to log on to the account. (Inherited from AuthenticablePrincipal.)
Public propertyStructuralObjectClassGets the structural object class directory attribute. (Inherited from Principal.)
Public propertySurnameGets or sets the surname for the user principal.
Public propertyUserCannotChangePasswordGets or sets a Boolean value that specifies whether the user can change the password for this account. Do not use this with a ComputerPrincipal. (Inherited from AuthenticablePrincipal.)
Public propertyUserPrincipalNameGets or sets the user principal name (UPN) associated with this principal. (Inherited from Principal.)
Public propertyVoiceTelephoneNumberGets or sets the voice telephone number for the user principal.

Points of Interest

Some other interesting methods I found in there were ChangePassword, ExpirePasswordNow, GetGroups, UnlockAccount, SetPassword, and Save. I just haven't had the chance to check them out. Thanks .NET 3.5!

History

  • Updated 9/23/09
    • Added spiff on exception handling
    • Updated code to use .DisplayName instead of .Name 

  • Updated 12/07/12
    • Fixed typo to UserPrincipal instead of UserPrinciple.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Veracity
United States United States
I'm a .NET developer, fluent in C# and VB.NET with a focus on SharePoint and experience in WinForms, WPF, Silverlight, ASP.NET, SQL Server. My roots come from a support/system administrator role so I know my way around a server room as well.

I have a passion for technology and I love what I do.

Comments and Discussions

 
GeneralRe: Thanks for the Contribution Pin
jabit3-Nov-10 5:25
jabit3-Nov-10 5:25 
GeneralRe: Thanks for the Contribution Pin
jabit3-Nov-10 5:34
jabit3-Nov-10 5:34 
GeneralRe: Thanks for the Contribution Pin
bigbro_198523-Nov-10 20:10
professionalbigbro_198523-Nov-10 20:10 
GeneralHere is what I do Pin
andre1234524-Sep-09 7:24
andre1234524-Sep-09 7:24 
GeneralRe: Here is what I do Pin
jabit24-Sep-09 7:49
jabit24-Sep-09 7:49 
GeneralGood Job Pin
Hollerith24-Sep-09 3:33
Hollerith24-Sep-09 3:33 
GeneralException Pin
Friedrich Brunzema23-Sep-09 11:29
Friedrich Brunzema23-Sep-09 11:29 
GeneralRe: Exception Pin
jabit23-Sep-09 12:05
jabit23-Sep-09 12:05 
GeneralRe: Exception Pin
Friedrich Brunzema24-Sep-09 6:34
Friedrich Brunzema24-Sep-09 6:34 
Hi,

what happens is that you get this exception when your machine is part of a domain, you're logged in with a domain user account, and you have disabled your network connection (either via software (disabled network adapter), or by plugging out the network cable). In this case, LoginUser() will still authenticate against cached credentials, but you won't get the user name. What we do in our application is to cache the full user name in a config file, and use the cached copy when the DomainController is not available. In a past era, I had written C++ code using the Net* API to get the full user name: (this old way of doing things may be more reliable)
BOOL CShowActiveDirUsers::GetFullUserName(LPTSTR szUser, LPTSTR szDomain, 
							LPTSTR szFullUserName, LPTSTR szDescription)
{
	BOOL	bResult = FALSE;
	LPWSTR	pServer = NULL;
	BOOL	bLocal = FALSE;
	TCHAR	szComputerName[_MAX_PATH];
	TCHAR   szDomainName[_MAX_PATH];
	TCHAR   szServer[_MAX_PATH];
	TCHAR   szPDC[_MAX_PATH];
	DWORD	dwLevel = 10;
	LPUSER_INFO_10 pUserInfoBuffer = NULL;

	// init
	ZeroMemory(szComputerName, _MAX_PATH);
	ZeroMemory(szDomainName, _MAX_PATH);
	ZeroMemory(szServer, _MAX_PATH);
	ZeroMemory(szPDC, _MAX_PATH);
	

	GetLocalComputerName(szComputerName);

	if (_tcsicmp(szComputerName, szDomain) == 0)
		bLocal = TRUE;

	// for active directory native, szUser comes in as user@domain.com
	if (!bLocal) 
	{
		GetDCName(szPDC, szDomain);
		if (_tcschr(szUser, AT) )
		{
			GetUserAndDomainNameFromUPN(szUser, szFullUserName, szDomainName);
			_tcscpy(szUser, szFullUserName);
			_tcscpy(szDomain, szDomainName);
		}
	}
	else
	{
		NetApiBufferAllocate(_MAX_PATH,  (LPVOID*)&pServer);
		ZeroMemory(pServer, _MAX_PATH);
		_tcscpy(pServer, DOUBLE_BACKSLASH);
		_tcscat(pServer, szComputerName);

	}

	// grab the details of the user account, 
	// may fail if AD=native & user not in proper security group
	if (NERR_Success == NetUserGetInfo(szPDC, szUser, dwLevel, 
											(LPBYTE*)&pUserInfoBuffer))
	{
		if (pUserInfoBuffer)
		{
			_tcscpy(szFullUserName, pUserInfoBuffer->usri10_full_name);
			_tcscpy(szDescription, pUserInfoBuffer->usri10_comment);
			bResult = TRUE;
		}
	}

	if (pUserInfoBuffer)
		NetApiBufferFree(pUserInfoBuffer);

	if (pServer)
		NetApiBufferFree(pServer);

	return bResult;
}


Having said all of this, I noticed that our friend UserPrinciple.Current.Name cam also fail if the domain user is not setup properly:
To see this, you need domain admin priviliges on the domain under question, and you need to use Active Directory Users and Computers control panel applet (under Administration) to edit the user. The Active directory management tools can be gotten from Microsoft, installed, then they appear in the control panel.

You then go to the user properties User Properties->Account page. Here you get two entries
Editbox (for username) Combobox (containing @yourdomain.com)
as well as
User Logon Name Pre Windows 2000
(Grayed out edit box containg YOURDOMAIN\) and Edit box for the username.

It is possible to clear out the top entry user@yourdomain.com and have only the bottom entry set YOURDOMAIN\user. In this scenario, you do get the exception.
You also get the exception if your primary domain controller runs out of disk space. How do I know? It happenend on our Primary Domain controller, and we got the exception.

Testing this is pretty complicated, because you really don't know what will happen in any particular network setup and configuration. I have found that Active Directory in Native mode (no backwards compatibility to NT4 style domain controllers) can behave differently than Native Mode Active directory installations. This setting (at least used to be) available only when you installed the Active Directory server.

Sorry for the long post - Anyways- I do think its good that you wrote, it does get indexed by Google, and this helps people looking for answers.

Friedrich Brunzema
GeneralRe: Exception Pin
jabit24-Sep-09 8:24
jabit24-Sep-09 8:24 
GeneralThank you Pin
noofny15-Sep-09 14:33
noofny15-Sep-09 14:33 
GeneralRe: Thank you Pin
jabit15-Sep-09 18:26
jabit15-Sep-09 18:26 
GeneralMy answer is THANKS Pin
Del Mitchell15-Sep-09 3:13
Del Mitchell15-Sep-09 3:13 
GeneralRe: My answer is THANKS Pin
jabit15-Sep-09 4:28
jabit15-Sep-09 4:28 
GeneralMy vote of 1 Pin
Country Man15-Sep-09 1:56
Country Man15-Sep-09 1:56 
RantRe: My vote of 1 Pin
jabit15-Sep-09 4:25
jabit15-Sep-09 4:25 
GeneralRe: My vote of 1 Pin
Slacker00729-Mar-11 5:43
professionalSlacker00729-Mar-11 5:43 
GeneralMore possible Pin
Not Active11-Sep-09 9:37
mentorNot Active11-Sep-09 9:37 
GeneralRe: More possible Pin
jabit11-Sep-09 9:44
jabit11-Sep-09 9:44 
GeneralRe: More possible Pin
Not Active11-Sep-09 9:48
mentorNot Active11-Sep-09 9:48 
GeneralRe: More possible Pin
jabit11-Sep-09 9:58
jabit11-Sep-09 9:58 
GeneralRe: More possible Pin
Not Active11-Sep-09 10:22
mentorNot Active11-Sep-09 10:22 
GeneralNot much here Pin
PIEBALDconsult11-Sep-09 9:31
mvePIEBALDconsult11-Sep-09 9:31 
GeneralRe: Not much here Pin
jabit11-Sep-09 9:41
jabit11-Sep-09 9:41 
GeneralRe: Not much here Pin
PIEBALDconsult11-Sep-09 11:31
mvePIEBALDconsult11-Sep-09 11:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.