From: Starbuck on
Hi Guys,

We are still running Svr2003r2 in our environment.

Given the fact that over the last months we've had a lot of
contractor accounts expire, and some of those have caused disruption
in the ability for the contractor to fulfill their duties, I'd like to
put in place a process or tool that gives us a head's up to accounts
that are going to expire in the next 2 weeks.

Has anyone ever done this before?
Is this something that could be managed within AD?
Or maybe it could be scripted using something like "oldcmp"?
If not, how can we make this happen?

Ultimately the process would be a note sent to HR that the account
will expire soon, and that will provide a buffer time of a couple of
weeks to get a contract renewed.

Thanks for your input.



*$
aa#2290
From: Richard Mueller [MVP] on

"Starbuck" <Starbuck(a)BogusDomain.com> wrote in message
news:pt2dp55k5blnb2ggaj48g0ptj6sqcpl55p(a)4ax.com...
> Hi Guys,
>
> We are still running Svr2003r2 in our environment.
>
> Given the fact that over the last months we've had a lot of
> contractor accounts expire, and some of those have caused disruption
> in the ability for the contractor to fulfill their duties, I'd like to
> put in place a process or tool that gives us a head's up to accounts
> that are going to expire in the next 2 weeks.
>
> Has anyone ever done this before?
> Is this something that could be managed within AD?
> Or maybe it could be scripted using something like "oldcmp"?
> If not, how can we make this happen?
>
> Ultimately the process would be a note sent to HR that the account
> will expire soon, and that will provide a buffer time of a couple of
> weeks to get a contract renewed.
>
> Thanks for your input.
>
>
>
> *$
> aa#2290

Below is a script I wrote a few months ago that documents the accounts that
will expire in the next 14 days (or whatever number of days is specified):

' AcctsAboutToExpire.vbs
' VBScript program to find accounts that will expire in the
' next 14 days.
Option Explicit

Dim objShell, lngBiasKey, lngTZBias
Dim adoConnection, adoCommand, objRootDSE, strDNSDomain
Dim strBase, strFilter, strAttributes, strQuery
Dim adoRecordset, strNTName, strDN
Dim dtmCritical, lngSeconds, str64Bit
Dim objDate, dtmExpire

' 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
lngTZBias = lngBiasKey
ElseIf (UCase(TypeName(lngBiasKey)) = "VARIANT()") Then
lngTZBias = 0
For k = 0 To UBound(lngBiasKey)
lngTZBias = lngTZBias + (lngBiasKey(k) * 256^k)
Next
End If

' Determine critical date 14 days in future.
dtmCritical = DateAdd("d", 14, Now())

' Convert to UTC.
dtmCritical = DateAdd("n", lngTZBias, dtmCritical)

' Convert to seconds since 1/1/1601
lngSeconds = DateDiff("s", #1/1/1601#, dtmCritical)

' Convert to 100-nanosecond intervals
str64Bit = CStr(lngSeconds) & "0000000"

' Setup ADO objects.
Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection

' Search entire Active Directory domain.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
strBase = "<LDAP://" & strDNSDomain & ">"

' Filter on user objects that expire in next 14 days.
strFilter = "(&(objectCategory=person)(objectClass=user)" _
& "(accountExpires<=" & str64Bit & ")(!accountExpires=0))"

' Comma delimited list of attribute values to retrieve.
strAttributes = "distinguishedName,sAMAccountName,accountExpires"

' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Run the query.
Set adoRecordset = adoCommand.Execute

' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
' Retrieve values and display.
strNTName = adoRecordset.Fields("sAMAccountName").Value
strDN = adoRecordset.Fields("distinguishedName").Value & ""
Set objDate = adoRecordset.Fields("accountExpires").Value
dtmExpire = Integer8Date(objDate, lngTZBias)
Wscript.Echo strDN & "," & strNTName & "," & dtmExpire
' Move to the next record in the recordset.
adoRecordset.MoveNext
Loop

' Clean up.
adoRecordset.Close
adoConnection.Close

Function Integer8Date(ByVal objDate, ByVal lngBias)
' Function to convert Integer8 (64-bit) value to a date, adjusted for
' local time zone bias.
Dim lngAdjust, lngDate, lngHigh, lngLow
lngAdjust = lngBias
lngHigh = objDate.HighPart
lngLow = objdate.LowPart
' Account for error in IADsLargeInteger property methods.
If (lngLow < 0) Then
lngHigh = lngHigh + 1
End If
If (lngHigh = 0) And (lngLow = 0) Then
lngAdjust = 0
End If
lngDate = #1/1/1601# + (((lngHigh * (2 ^ 32)) _
+ lngLow) / 600000000 - lngAdjust) / 1440
' Trap error if lngDate is ridiculously huge.
On Error Resume Next
Integer8Date = CDate(lngDate)
If (Err.Number <> 0) Then
On Error GoTo 0
Integer8Date = #1/1/1601#
End If
On Error GoTo 0
End Function

--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--