Click here to Skip to main content
14,267,679 members

How to get the REAL lastlogon datetime from Active Directory

Rate this:
4.67 (7 votes)
Please Sign up or sign in to vote.
4.67 (7 votes)
21 Mar 2013CPOL
This article describes how to get the real lastlogon datetime from an user from Active Directory and how to use custom Active Directory attributes.


This article describes how to get the real last-logon date-time from an user from Active Directory and how to use custom Active Directory attributes.


The .NET System.DirectoryServices.AccountManagement classes (from Framework 3.5) provide some neat functionality to access active directory users in a rather simple way. Retrieving a user is as simple as this:

using (var adContext = new PrincipalContext(ContextType.Domain, ADDomainName, ADContainer)
    username = "ADusername";
    var foundUser = UserPrincipal.FindByIdentity(adContext, username);
    if (foundUser != null)
        // do all sorts of neat stuff with user object

Now you would expect (as any other normal human being) that getting the lastlogon datetime from the Active Directory user is as simple as this from the UserPrincipal object we just created:

var lastlogonDateTime = founduser.LastLogon;  

 But unfortunately it isn't. After some research I found the following: 'Because the lastLogon attribute is not replicated throughout the domain, if our new user has never logged on to domain controller B then domain controller B will have no knowledge of the user’s last logon time.' 

Anyway, anyhow, it doesn't come up with the right last-logon time. It simply doesn't work, how do we solve this? This gave me a severe headache. 

It is there, but it is hidden. You must retrieve the right time by using extension attributes. By extending the Userprincipal class, you can access these attributes. Not only the real lastlogon time, but also different properties like fax number and so on.  

Using the code  

Below is my extended Userprincipal class which you can use instead of UserPrincipal

using System;
using System.DirectoryServices.AccountManagement;
using System.Reflection;

namespace MyNameSpace
    /// <summary>
    /// some properties must be retrieved by getting extended properties
    /// this is unfortunately a protected method and only accessible
    /// by using our own derived user from UserPrincipal
    /// </summary>
    public class UserPrincipalExtended : UserPrincipal
        public UserPrincipalExtended(PrincipalContext context) : base(context) { }

        public UserPrincipalExtended(PrincipalContext 
            string samAccountName, 
            string password,
            bool enabled)
            : base(context, samAccountName, password, enabled) { }

        public static new UserPrincipalExtended FindByIdentity(PrincipalContext context,
                                                       string identityValue)
            return (UserPrincipalExtended)FindByIdentityWithType(context,

        public static new UserPrincipalExtended FindByIdentity(PrincipalContext context,
                                                       IdentityType identityType,
                                                       string identityValue)
            return (UserPrincipalExtended)FindByIdentityWithType(context,

        #region custom attributes
        public DateTime? RealLastLogon
                if (ExtensionGet("LastLogon").Length > 0)
                    var lastLogonDate = ExtensionGet("LastLogon")[0];
                    var lastLogonDateType = lastLogonDate.GetType();

                    var highPart = (Int32)lastLogonDateType.InvokeMember("HighPart", 
                        BindingFlags.GetProperty, null, lastLogonDate, null);
                    var lowPart = (Int32)lastLogonDateType.InvokeMember("LowPart", 
                        BindingFlags.GetProperty | BindingFlags.Public, null, lastLogonDate, null);

                    var longDate = ((Int64)highPart << 32 | (UInt32)lowPart);

                    return longDate > 0 ? (DateTime?) DateTime.FromFileTime(longDate) : null;

                return null;

This will give you the proper LastLogon datetime. And you can add properties to retrieve other (custom) attributes for future purposes: 

public string HomePage
        if (ExtensionGet("HomePage").Length != 1)
            return null;
        return (string)ExtensionGet("HomePage")[0];
    set { this.ExtensionSet("HomePage", value); }

This is very convenient as the original Userprincipal class only exposes about 10% of the active directory attributes.  

Mind you use the attributes above the class UserPrincipalExtended. Copy the class literally in your project, change only the namespace and everything will work fine.  Good luck! 


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


About the Author

Netherlands Netherlands
No Biography provided

Comments and Discussions

QuestionNot really working Pin
maro00925-Mar-13 13:17
membermaro00925-Mar-13 13:17 
GeneralLastLogonTimeStamp Pin
Narfix25-Mar-13 1:13
professionalNarfix25-Mar-13 1:13 
GeneralMy vote of 4 Pin
Prasad Khandekar21-Mar-13 10:09
professionalPrasad Khandekar21-Mar-13 10:09 

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.

Posted 21 Mar 2013


10 bookmarked