Today I was asked to change some text to the email that is being sent to the users who's password is about to expire. Now being the quick & dirty developer that I was (.. really.. I'm a professional now), this line of text is hard coded in the source. So I had to open my old solution file and came to the discovery that this piece of code was still based on Password Reminder updated! and not utilizing the new features of .NET 3.5 where we have some actual AD support in the DirectoryServices namespace. Therefore I decided to update this solution to make use of it so here it is. The best part is that it cleans my code up quite drastically as well!
Instead of this :
DirectoryEntry entry = new DirectoryEntry("LDAP://domain.com");
DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(SAMAccountName=" + LogUser + ")";
SearchResult LDAPresult = search.FindOne();
entry = LDAPresult.GetDirectoryEntry();
// Pulling the informtion on when the password was last changed and converting it to a LargeInteger.
LargeInteger liAcctPwdChange = entry.Properties["pwdLastSet"].Value as LargeInteger;
// Convert the highorder/loworder parts of the property pulled to a long.
long dateAcctPwdChange = (((long)(liAcctPwdChange.HighPart) << 32) + (long)liAcctPwdChange.LowPart);
// Convert FileTime to DateTime and get what today's date is.
DateTime dtNow = DateTime.Now;
// I added 180 days because I know what my password expiration is set to, if not you need to pull that information and add the number of days it is set for.
CultureInfo ci = new CultureInfo("nl-NL");
DateTime dtAcctPwdChange = DateTime.FromFileTime(dateAcctPwdChange).AddDays(180);
string strAcctPwdChange = DateTime.FromFileTime(dateAcctPwdChange).ToString("d",ci);
string strAcctPwdExpires = DateTime.FromFileTime(dateAcctPwdChange).AddDays(180).ToString("d",ci);
// Calculate the difference between the date the pasword was changed, and what day it is now and display the # of days.
time = dtAcctPwdChange - dtNow;
if (time.Days < 20 && time.Days >= 0)
if (Convert.ToInt32(entry.Properties["userAccountControl"].Value.ToString() == 544))
We now have this :
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "DOMAIN", "DC=DOMAIN,DC=COM");
DateTime dt = DateTime.Today;
PrincipalSearchResult<UserPrincipal> results = UserPrincipal.FindByPasswordSetTime(ctx, dt.AddDays(-160), MatchType.LessThanOrEquals);
foreach (UserPrincipal result in results)
Pretty good stuff eh? ;)