How Can I Determine When an Active Directory User Account will Expire?
Hey, Scripting Guy! How can I determine when an Active Directory user account will expire?
Hey, JK. By the way, please accept our apologies for hiding under the desk and pretending we weren’t in when your question arrived; we always get a little nervous any time we get questions involving dates and Active Directory. That’s because Active Directory uses a number of different methods for storing dates and times, some of which are downright weird. For example, the LastLogon time is stored as a Large Integer value, and represents the number of seconds that elapsed between the 0 hour on January 1, 1601 and the time the user last logged on to the domain. (We kid you not.) VBScript can’t handle Large Integer values directly; therefore we need to go through all sorts of machinations involving higher mathematics, conversion algorithms, and downright wishful thinking in order to turn the Large Integer value into something VBScript can handle. And even then we don’t actually have a date and time, just a value that even more mathematical manipulation can eventually turn into a date and time.
Note. For a more detailed explanation of this issue – and others – surrounding the last logon time see this article in the Scripting for Windows Server 2003 center.
Fortunately, though, we can determine when a user account will expire without resorting to quantum mechanics or black magic. This doesn’t mean that the AccountExpirationDate attribute – the property that tells us when an account expires – isn’t without a quirk or two, but at least those quirks are easy enough to work around.
Let’s take a look at a script that tells when the Ken Myer user account expires:
On Error Resume Next
Set objUser = GetObject(“LDAP://cn=MyerKen,ou=Finance,dc=fabrikam,dc=com”)
dtmAccountExpiration = objUser.AccountExpirationDate
If Err.Number = -2147467259 OR dtmAccountExpiration = #1/1/1970# Then WScript.Echo “This account has no expiration date.” Else WScript.Echo “Account expiration date: ” & objUser.AccountExpirationDate End If
To begin with, you might have noticed the very first line in the script: On Error Resume Next. Typically we don’t include error-handling in our sample scripts; error-handling, while important in real-life scripting, often obscures the key points in our sample scripts, scripts designed more for educational purposes than for immediate use in the real world. In this case, however, error-handling is a must; that’s because an error will occur if no expiration date has been specified for an account. If we don’t anticipate and trap that error, our script will fail. Thus we start things out with On Error Resume Next; this will allow our script to continue on should it encounter an account that has no expiration date.
In line 2 we bind to the Ken Myer account in Active Directory; following that we store the value of the AccountExpirationDate in a variable named dtmAccountExpiration. This is the point where an error can occur: if the user account has no specified expiration date then error number -2147467259 is generated. We need to check to see if that error has occurred.
We also need to check for another eccentric feature of AccountExpirationDate. In Active Directory you can configure a user account so it never expires; when you do that, the AccountExpirationDate is set for January 1, 1970. (Yes, that is a weird way to ensure that an account does not expire.) If we get back error number -2147467259 that means no expiration date has been set for the account; that means the account does not expire. However, if we get back an account expiration date of January 1, 1970, that also means that the account does not expire. Therefore, we need to use an If-Then statement that checks for both of these possibilities:
If Err.Number = -2147467259 OR dtmAccountExpiration = #1/1/1970# Then
As you can see, if the error number (Err.Number) is equal to -2147467259 or if the account expiration date is January 1, 1970 (1/1/1970) we echo a message stating that the account has no expiration date; otherwise we echo back the expiration date. It’s weird, but it works, and at least we don’t have to hide under the desk. (Although that wasn’t a total loss: we did find our stapler, a bunch of paperclips, and the other half of that sandwich while we were under there.)