Search code examples
c#active-directorycustom-attributesadamadlds

Search Active Directory (AD LDS) by DateTime custom attribute


I have added custom attribute lastLogonTime syntax: UTC Coded Time. I extended UserPrincipal class to GET/SET that custom attribute.

enter image description here

...
[DirectoryProperty("lastLogonTime")]
public DateTime? LastLogonTime
{
   get
   {
      object[] result = this.ExtensionGet("lastLogonTime");
      if (result != null && result.Count() > 0) return (DateTime?)result[0];
           return null;
   }
   set
   {
      this.ExtensionSet("lastLogonTime", value);
   }
}
...

I have also extended AdvancedFilters to be able to search by this custom attribute.

MyUserPrincipalSearch searchFilter;

new public MyUserPrincipalSearch AdvancedSearchFilter
{
   get
   {
      if (null == searchFilter)
          searchFilter = new MyUserPrincipalSearch(this);
      return searchFilter;
   }
}

public class MyUserPrincipalSearch: AdvancedFilters
{
   public MyUserPrincipalSearch(Principal p) : base(p) { }
   public void LastLogonTime (DateTime? lastLogonTime, MatchType mt)
   {
     this.AdvancedFilterSet("lastLogonTime", lastLogonTime.Value, typeof(DateTime?), mt);
   }
}

Now, I would like to search through all users who has lastLogonTime less than a day.

using (PrincipalContext ctx = ADLDSUtility.Users)
{
   MyUserPrincipal filter = new MyUserPrincipal(ctx);
   filter.AdvancedSearchFilter.LastLogonTime((DateTime.Now - new TimeSpan(1,0,0,0,0)), MatchType.LessThan);
   PrincipalSearcher ps = new PrincipalSearcher(filter);
   foreach (MyUserPrincipal p in ps.FindAll())
   {
      //my custom code
   }
}

The above search is not returning me any results. I have test users who have not logged in in the last couple days.

I have tried MatchType.GreaterThan, MatchType.Equals. None of them are returning any results, yet there're users who match those criteria.

The only filter that does work is

filter.AdvancedSearchFilter.LastLogonTime(DateTime.Now , MatchType.NotEquals);

But this is basically returning all users. Any ideas why my search result is not returning any results?

My goal is to search for all users who's last logon time is less than X days.

I'm open to other solutions as long as I get those users.

P.S. I do know a way around this. Loop through all users, get their lastLogonTime and then do a comparison, but that's just an overkill for what I'm doing.


Solution

  • After spending sometimes on this issue, I found the problem.

    As I mentioned on my post the custom attribute lastLogonTime has syntax: UTC Coded Time. However, the date and time is not getting stored as DateTime. It's actually getting stored as string in this format:

    yyyyMMddHHmmss.0Z

    How I ended up solving this issue is by modifying my AdvancedSearchFilter.LastLogonTime to search using formatted string.

    public void LastLogonTime (DateTime? lastLogonTime, MatchType mt)
    {
       const string lastLogonTimeFormat = "yyyyMMddHHmmss.0Z";
       this.AdvancedFilterSet("lastLogonTime", lastLogonTime.Value.ToUniversalTime().ToString(lastLogonTimeFormat), typeof(string), mt);
    }
    

    Hope this helps someone.