C# (CSharp, C-Sharp) Windows Active Directory last logon

Hi guys

Please note, many threads were referred in order to compile the script attached below & all I did was re-arranging in order for better reading/formatting

(And I insure that the script works under following scenarios:

  1. You are a domain administrator
  2. You are administrating Windows 2003 onwards Windows domain
  3. Your puter is connected to the domain network ;)

)

Referenced websites/threads

  1. http://stackoverflow.com/questions/15775264/searching-for-lastlogon-attribute-of-user-in-multiple-domain-servers
  2. https://www.codeproject.com/kb/security/lastlogonacrossallwindows.aspx#_comments
  3. http://codebeautify.org/csharpviewer (for formatting the C# code)

How to test the code

Start Visual Studio (I am using 2013 Professional edition, you can use any of the community editions to test the scripts)

Create a new C# Console Application and name it llogon (else you need to change the namespace name “llogon” according to the name you have chosen for your new project.

Add the following references to your project

  1. “Framework -> System.DirectoryServices”
  2. “Browse and add -> C:\Windows\System32\activeds.tlb”

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//Added by Rajesh

//using System.Management;
//using System.Data;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;
//http://stackoverflow.com/questions/33274162/the-namespace-of-iadslargeinteger
//ActiveDS namespace
using ActiveDs; // Namespace added via ref to C:\Windows\System32\activeds.tlb
//https://www.codeproject.com/kb/security/lastlogonacrossallwindows.aspx

namespace llogon
{
    class Program
    {
        static void Main(string[] args)
        {
            // Get the root entry
            DirectoryEntry rootDSE = new DirectoryEntry("LDAP://RootDSE");
            string configurationNamingContext =
             (string)rootDSE.Properties["configurationNamingContext"].Value;
            string defaultNamingContext =
             (string)rootDSE.Properties["defaultNamingContext"].Value;
            Dictionary<string, Int64> lastLogons = new Dictionary<string, Int64>();
            // Get all the domain controllers
            DirectoryEntry deConfig = new DirectoryEntry("LDAP://" + configurationNamingContext);
            DirectorySearcher dsConfig = new DirectorySearcher(deConfig);
            dsConfig.Filter = "(objectClass=nTDSDSA)";
            foreach (SearchResult srDomains in dsConfig.FindAll())
            {
                DirectoryEntry deDomain = srDomains.GetDirectoryEntry();
                if (deDomain != null)
                {
                    string dnsHostName =
                     deDomain.Parent.Properties["DNSHostName"].Value.ToString();
                    // Get all the users for that domain
                                   DirectoryEntry deUsers =
                     new DirectoryEntry("LDAP://" + dnsHostName + "/" + defaultNamingContext);
                    DirectorySearcher dsUsers = new DirectorySearcher(deUsers);
                    dsUsers.Filter = "(&(objectCategory=person)(objectClass=user))";
                    foreach (SearchResult srUsers in dsUsers.FindAll())
                    {
                        DirectoryEntry deUser = srUsers.GetDirectoryEntry();
                        if (deUser != null)
                        {
                            // Get the distinguishedName and lastLogon for each user
                            // Save the most recent logon for each user in a Dictionary object
                            string distinguishedName = deUser.Properties["distinguishedName"].Value.ToString();
                            Int64 lastLogonThisServer = new Int64();
                            if (deUser.Properties["lastLogon"].Value != null)
                            {
                                IADsLargeInteger lgInt =
                                 (IADsLargeInteger)deUser.Properties["lastLogon"].Value;
                                lastLogonThisServer = ((long)lgInt.HighPart << 32) + lgInt.LowPart;
                            }

                            // Save the most recent logon for each user in a Dictionary object
                            if (lastLogons.ContainsKey(distinguishedName))
                            {
                                if (lastLogons[distinguishedName] < lastLogonThisServer)
                                {
                                    lastLogons[distinguishedName] = lastLogonThisServer;
                                }
                            }
                            else
                            {
                                lastLogons.Add(distinguishedName, lastLogonThisServer);
                            }
                            string readableLastLogon = DateTime.FromFileTime(lastLogonThisServer).ToString();
                            Console.WriteLine("User: " + distinguishedName + "Last logon: " +readableLastLogon);
                        }
                    }
                    Console.ReadLine();
                }
            }

        }
    }
}

Try the code & if you are stuck somewhere, do let me through the comments. I am working on a WPF C# project for a simple Active Directory Reporter / Asset Management System using WMI. Stay tuned & I will soon post the entire solution here :)

regards,

rajesh

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: