3
votes

How can I get a list of users from active directory?

Please see the page above. It answered most of my questions, but I get a problem when I try to get last logon time for a computer. Sorry if there was some way to comment on that page instead of making a whole new question because I didn't find such an option.

using (var context = new PrincipalContext(ContextType.Domain, "cat.pcsb.org"))
        {
            using (var searcher = new PrincipalSearcher(new ComputerPrincipal(context)))
            {
                foreach (var result in searcher.FindAll())
                {
                    DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
                    Console.WriteLine("Name: " + de.Properties["name"].Value);
                    Console.WriteLine("Last Logon Time: " + de.Properties["lastLogon"].Value);
                    Console.WriteLine();
                }
            }
        }
        Console.ReadLine();

I replaced UserPrincipal with ComputerPrincipal. Name and some other properties work fine, but logon doesn't. I've tried doing different things like casting it to DateTime (the cast failed) but nothing worked. The above just results in System.__ComObject. So what can I do to get it to get last logon time correctly?

2

2 Answers

8
votes

Why aren't you just using the the LastLogon property returned by ComputerPrincipal? (ComputerPrincipal is a AuthenicatablePrincipal)

using (var context = new PrincipalContext(ContextType.Domain, "cat.pcsb.org"))
{
    using (var searcher = new PrincipalSearcher(new ComputerPrincipal(context)))
    {
        foreach (var result in searcher.FindAll())
        {
            var auth = result as AuthenticablePrincipal;
            if(auth != null)
            {
                Console.WriteLine("Name: " + auth.Name);
                Console.WriteLine("Last Logon Time: " + auth.LastLogon);
                Console.WriteLine();
            }
        }
    }
}
Console.ReadLine();

Note that LastLogon is not a replicated property, so if you have more than one domain controller you need to query each controller and find out who gives the most recent result.

4
votes

You need to iterate through all domain controllers and find the lastest logon time.

The below code finds last logon time for a user.

public DateTime findlastlogon(string userName)

    {
        DirectoryContext context = new DirectoryContext(DirectoryContextType.Domain, "domainName");
        DateTime latestLogon = DateTime.MinValue;
        DomainControllerCollection dcc = DomainController.FindAll(context);
        Parallel.ForEach(dcc.Cast<object>(), dc1 =>
                {


                    DirectorySearcher ds;
                    DomainController dc = (DomainController)dc1;
                    using (ds = dc.GetDirectorySearcher())
                    {
                        try
                        {
                            ds.Filter = String.Format(
                              "(sAMAccountName={0})",
                              userName
                              );
                            ds.PropertiesToLoad.Add("lastLogon");
                            ds.SizeLimit = 1;
                            SearchResult sr = ds.FindOne();

                            if (sr != null)
                            {
                                DateTime lastLogon = DateTime.MinValue;
                                if (sr.Properties.Contains("lastLogon"))
                                {
                                    lastLogon = DateTime.FromFileTime(
                                      (long)sr.Properties["lastLogon"][0]
                                      );
                                }

                                if (DateTime.Compare(lastLogon, latestLogon) > 0)
                                {
                                    latestLogon = lastLogon;
                                    //servername = dc1.Name;
                                }
                            }
                        }
                        catch (Exception)
                        {

                        }                          
                    }
                });
        return latestLogon;
    }

To get last logon time for a computer replace sAMAccountName to Name.

ds.Filter = String.Format( "(Name={0})", userName );