Get a User's Full Name

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!

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):

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!

Share

About the Author

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.

your article looks good but I guess the class name should be UserPrincipal and not UserPrinciple and also this article looks good if have a DNS and AD.if the system is in work group I think it will be easy to use win32 functions to get all those details.

I think you would get a COM exception if try to get the same on a local machine.

No, you won't. The PrincipalContext class will work equally well with the SAM database, so long as you specify the correct ContextType in the constructor. The UserPrincipal.Current property will take care of this for you.

hi the qustion contains a Junk with my following question the bolded thing is my Question rest i have not added hope there is a miss use of my Account. Could that happen. please answer me for the Bolded thing.

Is there is a way to get the Current Login user image.

hai i cant include ("cryptopp551.dll") this dll in my C# project please say solution or send me any DLL file that is capable of encrypt a password by use of a key

hai i cant include ("cryptopp551.dll") this dll in my C# project please say solution or send me any DLL file that is capable of encrypt a password by use of a key

I don't know what you mean by "other images from my local drive". If you want a regular image just copy it using the standard methods in the System.IO.File or FileInfo class. Or simply don't bother removing the header and footer from the file:

hi,i hope i didn't mentioned it clear. other images means the image that are used as a profile images other than default system image. if i apply the default system image it works but when i suppose to apply the some images like photos downloaded from inter net or other images as my system login user profile image this code can not convert it. hope you understand my problem right.

hai i cant include ("cryptopp551.dll") this dll in my C# project please say solution or send me any DLL file that is capable of encrypt a password by use of a key

Please note that the code I posted hasn't been tested with Win XP or local accounts. But from reading those links local accounts should have the same file format as the domain accounts and are stored in the same directory. Just the filename will be different.

I would recommend caching the display name somehow when you are connected. Perhaps you could add and application setting for the display name and store the last found display name in it. Then if you get an exception (because you're offline) you can use the cached name. If you've never been able to get the display name you can default back to the System.Environment.UserName.

IF you can't cache the name:

There are other things you could try as well. For example, in another comment on my article, andre12345 gives a (longer) alternative method using WMI. You can also hook in to the "GetUserNameEx" method in the secur32.dll Win32 DLL. It gets a bit hairy wrapping the Win32 method in .NET if you've never done it before but here's an example:

The enum makes the code more self documenting but you could just as easily do:int returnValue = GetUserNameEx(3, buffer, ref bufferSize);

So if you absolutely need to get the name offline and can't cache it anywhere you can use this method. It turns the nice clean 1-liner into probably 10 or more lines of code but it works offline whether or not you're joined to a domain.

Wow, see how complicated that is! It's so much easier to just call "Sytstem.DirectoryServices.AccountManagement.UserPrinciple.Current.DisplayName". That's all you have to do and you're done. Why write 20 lines of code when you can do it with 1 and wrap it in a Try..Catch block??

Be aware that you can get a PrincipalServerDown exception if you're not connected to your network. This can also happen if the user is not properly configured in the Active Directory (only pre-windows 2000 compatible name set)

Thanks for the first constructive reply I've had. I did some testing and you will not receive the PrincipleServerDown exception if you're not logged in as a domain user but will if you are. I also found that I should be using UserPrinciple.Current.DisplayName instead of UserPrinciple.Current.Name.

Can you elaborate on "only pre-windows 2000 compatible name set"? Are you talking about the domain functional level? NT server?

I really doesn't matter though, the takeaway is to make sure and wrap this in a Try...Catch block and if you get an exception, just get the username instead (System.Environment.UserName or My.User.Name in VB).

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)

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.

I like the idea of caching the name. You could very simply store the name in an application setting. That way if it does fail, you catch it and just use the application setting instead and maybe silently log the failed query somewhere.

Out of disk space causes this error huh? Have fun trying to track that one down. I suppose running out of disk space on a DC would cause a lot of unexpected errors (they must not test that scenario very well at M$).

Thanks for the reply. The .UserDomainName gives you the domain name for the currently logged in user and .UserName gives you the same thing as VB's My.User.Name (MyDomain\Username). This approach actually gets the user's name so instead of "MyDom\jdoe" you get "John Doe"!

As I've explained, this namespace isn't automatically referenced for new projects and finding this gem took me some time. If you would've took the time to read my replies to the other posts you'd see that I'm trying to make it easier to find. You didn't find it useful because you weren't looking for a way to get a user's full name. Don't vote an article as useless just because YOU have no use for it.

If people open an article named "Get a User's Full Name", then they've found what they're looking for. Obviously you can use the namespace for so much more. I've been thinking about creating a blog so maybe that's a better medium for this kind of stuff. Thanks for the comment though.

That's the point, if someone is loking for information about System.DirectoryServices.AccountManagement, and article titled "Get a User's Full Name" will be ignored, not opened to see what else is in it.

Well, ignore it then lol. There's nothing in there about anything but getting a user's name since that's all I needed it for. I didn't know people here would be opposed to posting a simple article on a particular feature of the framework.

There's already a whole article on the namespace here: Using System.DirectoryServices.AccountManagement[^]
But it doesn't mention anything about the .Current.Name property there either. My whole point is that this information is not extremely easy to find so I wanted to put it out there.

So anyways, in the future I guess I'll reserve this kind of stuff for a blog...

You're probably right. But I don't have a blog and I just wanted to throw something up quick for people looking for an answer to this problem. Any suggestions for a quick and easy way to create a blog, I've been thinking about it for a while.
Thanks.