The AuthenticablePrincipal.LastPasswordSet property in the .NET library’s System.DirectoryServices.AccountManagement namespace specifies the last date and time that the password was set for an account. We use this property to read a number of pieces of data about Active Directory user accounts but there is an interesting anomaly with the LastPasswordSet property in the AuthenticablePrincipal wrapper class.
The LastPasswordSet property is a nullable DateTime that returns null when the underlying attribute in Active Directory, pwdLastSet, is actually null or when it is zero. This may not be an issue unless you want the true value of the elusive Active Directory setting of “User must change password at next logon.”
In this case, the LastPasswordSet property masks the true value by covering up the zero value. When the pwdLastSet value is null, the password has never been set and the user account truly has no password. However, when the pwdLastSet value is zero (0x0 in hex), this indicates that the user must change password at next logon. Reading the LastPasswordSet property of AuthenticablePrincipal does not show the zero value, though, meaning that if you need the value of user must change password at next logon then you need to read the underlying pwdLastSet attribute value from Active Directory instead of using the more convenient LastPasswordSet value.
The code snippet here shows how to read the pwdLastSet value and determine whether the password is truly null (the account has no password) or whether the user must change the password at next logon. Note that you must convert the pwdLastSet value to an Int64 for comparison.[sourcecode language=”csharp”] <pre>var isChangePasswordAtNextLogonSet = false;
var entry = new DirectoryEntry(); // Get a DirectoryEntry.
// Check out page 367 of the excellent book from Ryan Dunn and Joe Kaplan for the GetInt64() method implementation: http://ptgmedia.pearsoncmg.com/images/0321350170/samplechapter/Kaplan_ch10.pdf
var pwdLastSet = GetInt64(entry, "pwdLastSet");
if (pwdLastSet == 0)
// Check the userAccountControl’s UF_DONT_EXPIRE_PASSWD flag using the DirectoryEntry.
var userAccountControl = (int)entry.Properties["userAccountControl"];
// UF_DONT_EXPIRE_PASSWD hex value is 0x10000. Refer to http://msdn.microsoft.com/en-us/library/aa772300.aspx
// and http://msdn.microsoft.com/en-us/library/ms680832(v=vs.85).aspx for a full list of userAccountControl flags.
isChangePasswordAtNextLogonSet = (userAccountControl & 0x10000) == userAccountControl;
isChangePasswordAtNextLogonSet = true;