Search For Expired Accounts

Search For Expired Accounts

Post by Stev » Wed, 02 Jul 2003 17:59:45



Is there any way of executing an ADSI search that will return user
accounts which have expired (AccountExpirationDate)? I am trying to
find an alternative to individually binding to each of the 4000
accounts in my domain to work out this information.

Thanks

 
 
 

Search For Expired Accounts

Post by Richard Mueller [MVP » Thu, 03 Jul 2003 00:53:08



> Is there any way of executing an ADSI search that will return user
> accounts which have expired (AccountExpirationDate)? I am trying to
> find an alternative to individually binding to each of the 4000
> accounts in my domain to work out this information.

Hi,

ADO is the most efficient method to search AD for objects.
AccountExpirationDate is a property method of the user object, so it cannot
be retrieved with ADO. The attribute accountExpires represents the date the
user account expires. However, accountExpires is Integer8 (8 byte), which is
a 64-bit number. Some code is required to convert this number to a date. ADO
cannot filter on 64-bit numbers, so you must return all user objects,
convert each accountExpires value to a date, and test if it is in the past.

However, this is still far faster. You only need to bind to three objects
and execute a query. Also, you can only return user objects that have a
value assigned to the accountExpires attribute, so there probably are not
that many user objects to deal with anyway. A few things to account for - If
accountExpires is 0 or -1, the account never expires.

The following code displays the Distinguished Name of all user accounts in
the domain that have expired:

Option Explicit

Dim objRootDSE, strDNSDomain, objCommand, objConnection
Dim strBase, strFilter, strAttributes, strQuery, objRecordSet
Dim strDN
Dim objShell, lngBiasKey, lngBias
Dim lngDate, objDate, lngHigh, lngLow, dtmDate

' Obtain local Time Zone bias from machine registry.
Set objShell = CreateObject("Wscript.Shell")
lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" _
  & "TimeZoneInformation\ActiveTimeBias")
If UCase(TypeName(lngBiasKey)) = "LONG" Then
  lngBias = lngBiasKey
ElseIf UCase(TypeName(lngBiasKey)) = "VARIANT()" Then
  lngBias = 0
  For k = 0 To UBound(lngBiasKey)
    lngBias = lngBias + (lngBiasKey(k) * 256^k)
  Next
End If

' Determine DNS domain name.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")

' Use ADO to search Active Directory for all users
' that have a value assigned to accountExpires.
Set objCommand = CreateObject("ADODB.Command")
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection
strBase = "<LDAP://" & strDNSDomain & ">"

strFilter = "(&(objectCategory=person)(objectClass=user)" _
  & "(accountExpires=*))"
strAttributes = "distinguishedName,accountExpires"
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
objCommand.CommandText = strQuery
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 30
objCommand.Properties("Cache Results") = False
Set objRecordSet = objCommand.Execute

' Enumerate user objects.
' Output if account is expired.
Wscript.Echo "The following user accounts have expired"
Do Until objRecordSet.EOF
  lngDate = objRecordSet.Fields("accountExpires")
  On Error Resume Next
  Err.Clear
  Set objDate = lngDate
  If Err.Number = 0 Then
    On Error GoTo 0
    lngHigh = objDate.HighPart
    lngLow = objDate.LowPart
    ' Correct for inaccuracy in IADsLargeInteger property methods.
    If lngLow < 0 Then
      lngHigh = lngHigh + 1
    End If
    If Not ((lngHigh = 0) And (lngLow = 0)) Then
      If Not ((lngHigh = 0) And (lngLow = -1)) Then
        ' Convert to date in local time zone.
        dtmDate = #1/1/1601# + (((lngHigh * (2^32)) _
          + lngLow)/600000000 - lngBias)/1440
        ' Determine if expiration date in past.
        If Now > dtmDate Then
          strDN = objRecordSet.Fields("distinguishedName")
          Wscript.Echo strDN
        End If
      End If
    End If
  End If
  On Error GoTo 0
  objRecordSet.MoveNext
Loop
Wscript.Echo "Done"

' Clean up.
Set objRootDSE = Nothing
Set objDate = Nothing
Set objShell = Nothing
Set objCommand = Nothing
Set objConnection = Nothing
Set objRecordSet = Nothing

--
Richard
Microsoft MVP Scripting and ADSI
http://www.rlmueller.net
--

 
 
 

Search For Expired Accounts

Post by Stev » Thu, 03 Jul 2003 16:06:01


WOW!!! What can I say, thanks...



> > Is there any way of executing an ADSI search that will return user
> > accounts which have expired (AccountExpirationDate)? I am trying to
> > find an alternative to individually binding to each of the 4000
> > accounts in my domain to work out this information.

> Hi,

> ADO is the most efficient method to search AD for objects.
> AccountExpirationDate is a property method of the user object, so it cannot
> be retrieved with ADO. The attribute accountExpires represents the date the
> user account expires. However, accountExpires is Integer8 (8 byte), which is
> a 64-bit number. Some code is required to convert this number to a date. ADO
> cannot filter on 64-bit numbers, so you must return all user objects,
> convert each accountExpires value to a date, and test if it is in the past.

> However, this is still far faster. You only need to bind to three objects
> and execute a query. Also, you can only return user objects that have a
> value assigned to the accountExpires attribute, so there probably are not
> that many user objects to deal with anyway. A few things to account for - If
> accountExpires is 0 or -1, the account never expires.

> The following code displays the Distinguished Name of all user accounts in
> the domain that have expired:

> Option Explicit

> Dim objRootDSE, strDNSDomain, objCommand, objConnection
> Dim strBase, strFilter, strAttributes, strQuery, objRecordSet
> Dim strDN
> Dim objShell, lngBiasKey, lngBias
> Dim lngDate, objDate, lngHigh, lngLow, dtmDate

> ' Obtain local Time Zone bias from machine registry.
> Set objShell = CreateObject("Wscript.Shell")
> lngBiasKey = objShell.RegRead("HKLM\System\CurrentControlSet\Control\" _
>   & "TimeZoneInformation\ActiveTimeBias")
> If UCase(TypeName(lngBiasKey)) = "LONG" Then
>   lngBias = lngBiasKey
> ElseIf UCase(TypeName(lngBiasKey)) = "VARIANT()" Then
>   lngBias = 0
>   For k = 0 To UBound(lngBiasKey)
>     lngBias = lngBias + (lngBiasKey(k) * 256^k)
>   Next
> End If

> ' Determine DNS domain name.
> Set objRootDSE = GetObject("LDAP://RootDSE")
> strDNSDomain = objRootDSE.Get("defaultNamingContext")

> ' Use ADO to search Active Directory for all users
> ' that have a value assigned to accountExpires.
> Set objCommand = CreateObject("ADODB.Command")
> Set objConnection = CreateObject("ADODB.Connection")
> objConnection.Provider = "ADsDSOObject"
> objConnection.Open "Active Directory Provider"
> objCommand.ActiveConnection = objConnection
> strBase = "<LDAP://" & strDNSDomain & ">"

> strFilter = "(&(objectCategory=person)(objectClass=user)" _
>   & "(accountExpires=*))"
> strAttributes = "distinguishedName,accountExpires"
> strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
> objCommand.CommandText = strQuery
> objCommand.Properties("Page Size") = 100
> objCommand.Properties("Timeout") = 30
> objCommand.Properties("Cache Results") = False
> Set objRecordSet = objCommand.Execute

> ' Enumerate user objects.
> ' Output if account is expired.
> Wscript.Echo "The following user accounts have expired"
> Do Until objRecordSet.EOF
>   lngDate = objRecordSet.Fields("accountExpires")
>   On Error Resume Next
>   Err.Clear
>   Set objDate = lngDate
>   If Err.Number = 0 Then
>     On Error GoTo 0
>     lngHigh = objDate.HighPart
>     lngLow = objDate.LowPart
>     ' Correct for inaccuracy in IADsLargeInteger property methods.
>     If lngLow < 0 Then
>       lngHigh = lngHigh + 1
>     End If
>     If Not ((lngHigh = 0) And (lngLow = 0)) Then
>       If Not ((lngHigh = 0) And (lngLow = -1)) Then
>         ' Convert to date in local time zone.
>         dtmDate = #1/1/1601# + (((lngHigh * (2^32)) _
>           + lngLow)/600000000 - lngBias)/1440
>         ' Determine if expiration date in past.
>         If Now > dtmDate Then
>           strDN = objRecordSet.Fields("distinguishedName")
>           Wscript.Echo strDN
>         End If
>       End If
>     End If
>   End If
>   On Error GoTo 0
>   objRecordSet.MoveNext
> Loop
> Wscript.Echo "Done"

> ' Clean up.
> Set objRootDSE = Nothing
> Set objDate = Nothing
> Set objShell = Nothing
> Set objCommand = Nothing
> Set objConnection = Nothing
> Set objRecordSet = Nothing

 
 
 

1. Account Expire and Password does not expire

Hello,
I am trying to programmatically create a some users whose accounts DO expire
but whose passwords DO NOT expire.

Here is the code:

option explicit
Dim intCustNum, strCustID, objParent, objUser, StrParent, strCN,
strPassword, strUPN, strSAMName, strScriptPath, strProfilePath,
strDescription, strAccountExpireDate
intCustNum = 123
strCustID = "test"

strParent = "OU=" & strCustID & ",OU=clients,DC=domain,DC=com"
strCN = "CN=123test3"
strSAMName = "123test3"

strPassword = "password"
strScriptPath = "000.bat"
strProfilePath = "\\server\mn000testsch\%username%"
strDescription = "Test User"
strAccountExpireDate = Date + 31
Set objParent = GetObject("LDAP://" & strParent)
Set objUser = objParent.Create("user", strCN)

'  Populate user object
objUser.Put "sAMAccountName", strSAMName
objUser.Put "userPrincipalName", strUPN
objUser.Put "ScriptPath", strScriptPath
objUser.Put "ProfilePath", strProfilePath
objUser.Put "description", strDescription
objUser.SetInfo

' Set password on user object
objUser.SetPassword strPassword
objUser.AccountDisabled = False
objUser.SetInfo

This all works fine so far, but I want to set the account expire date this
user and check the password never expires check box.
To set the account expiration date I tried:

'  Populate user object
...
objUser.Put "accountExpires", strAccountExpireDate

But that returns an "unspecified error"

And for the password does not expire checkbox I havn't been able to figure
out what to "put" to set this.

All suggestions graciously accepted....

Thanks,

--

Sam Doyle
remove MY SHOES to reply

2. WANTED: Legacy StorageWorks....UK

3. Your Account at Mail.china.com has expired.

4. Lisp to save & close the current Dwg?

5. Guest Account Expired

6. Hidden Files in FrontPage 2000 Discussion Group

7. Win98 can't access NT ws: user account expired???

8. supra 288 reliability?

9. Need Help Please! Expire accounts?

10. Expired accounts?

11. Can User Account Password be set to expire on a date?

12. How to retrieve a list of user accounts that will expire.

13. Mapping NT accounts to Unix accounts without creating new accounts