{"id":69373,"date":"2005-07-18T16:30:00","date_gmt":"2005-07-18T16:30:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2005\/07\/18\/how-can-i-determine-when-an-active-directory-user-account-will-expire\/"},"modified":"2005-07-18T16:30:00","modified_gmt":"2005-07-18T16:30:00","slug":"how-can-i-determine-when-an-active-directory-user-account-will-expire","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-determine-when-an-active-directory-user-account-will-expire\/","title":{"rendered":"How Can I Determine When an Active Directory User Account will Expire?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> \n<P>Hey, Scripting Guy! How can I determine when an Active Directory user account will expire?<BR><BR>&#8212; JK<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\"><\/A> \n<P>Hey, JK. By the way, please accept our apologies for hiding under the desk and pretending we weren\u2019t in when your question arrived; we always get a little nervous any time we get questions involving dates and Active Directory. That\u2019s 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\u2019t 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 <I>can<\/I> handle. And even <I>then<\/I> we don\u2019t actually have a date and time, just a value that even more mathematical manipulation can eventually turn into a date and time.<\/P>\n<TABLE class=\"dataTable\" id=\"E6C\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. For a more detailed explanation of this issue &#8211; and others &#8211; surrounding the last logon time see <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/topics\/win2003\/lastlogon.mspx\"><B>this article<\/B><\/A> in the <A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/win2003.mspx\"><B>Scripting for Windows Server 2003<\/B><\/A> center.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>Fortunately, though, we can determine when a user account will expire without resorting to quantum mechanics or black magic. This doesn\u2019t mean that the <B>AccountExpirationDate<\/B> attribute &#8211; the property that tells us when an account expires &#8211; isn\u2019t without a quirk or two, but at least those quirks are easy enough to work around.<\/P>\n<P>Let\u2019s take a look at a script that tells when the Ken Myer user account expires:<\/P><PRE class=\"codeSample\">On Error Resume Next<\/p>\n<p>Set objUser = GetObject(&#8220;LDAP:\/\/cn=MyerKen,ou=Finance,dc=fabrikam,dc=com&#8221;)<\/p>\n<p>dtmAccountExpiration = objUser.AccountExpirationDate <\/p>\n<p>If Err.Number = -2147467259 OR dtmAccountExpiration = #1\/1\/1970# Then\n    WScript.Echo &#8220;This account has no expiration date.&#8221;\nElse\n    WScript.Echo &#8220;Account expiration date: &#8221; &amp; objUser.AccountExpirationDate\nEnd If\n<\/PRE>\n<P>To begin with, you might have noticed the very first line in the script: <B>On Error Resume Next<\/B>. Typically we don\u2019t 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\u2019s because an error will occur if no expiration date has been specified for an account. If we don\u2019t 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.<\/P>\n<P>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.<\/P>\n<P>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 <I>is<\/I> 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 <I>also<\/I> means that the account does not expire. Therefore, we need to use an If-Then statement that checks for both of these possibilities:<\/P><PRE class=\"codeSample\">If Err.Number = -2147467259 OR dtmAccountExpiration = #1\/1\/1970# Then\n<\/PRE>\n<P>As you can see, if the error number (<B>Err.Number<\/B>) is equal to -2147467259 <I>or<\/I> 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\u2019s weird, but it works, and at least we don\u2019t have to hide under the desk. (Although that wasn\u2019t a total loss: we did find our stapler, a bunch of paperclips, and the other half of that sandwich while we were under there.)<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I determine when an Active Directory user account will expire?&#8212; JK Hey, JK. By the way, please accept our apologies for hiding under the desk and pretending we weren\u2019t in when your question arrived; we always get a little nervous any time we get questions involving dates and Active Directory. [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[7,3,20,5],"class_list":["post-69373","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-active-directory","tag-scripting-guy","tag-user-accounts","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I determine when an Active Directory user account will expire?&#8212; JK Hey, JK. By the way, please accept our apologies for hiding under the desk and pretending we weren\u2019t in when your question arrived; we always get a little nervous any time we get questions involving dates and Active Directory. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/69373","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=69373"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/69373\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=69373"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=69373"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=69373"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}