#192885 - 2009-03-14 12:23 AM
Re: User Account Locked Notification
[Re: JeffS ]
Glenn Barnas
KiX Supporter
Registered: 2003-01-28
Posts: 4401
Loc: New Jersey
It just so happens that I have a script that runs every Monday morning that checks for expired, locked, and about-to-expire accounts. It generates a report and emails the report to specific users. Since this does 173% of what you need, I've posted it here and you can remove the unwanted parts and customize it to your specific needs..
The core pieces are there - look for accounts that are locked, send email.
Glenn
;; KixGenerated: 2008/10/22 10:00:32
Break On
Dim $Members , $Member ; array of domain user members, enumerator var
Dim $I ; index var
Dim $objUser ; AD user query object pointer
Dim $Flags ; user flags
Dim $ExpDate , $Days ; expiration date, days remaining
Dim $LStat , $EStat ; locked and Expired status flags
Dim $RptData [0 ], $R ; report array, record pointer
Dim $Header ; report page header
Dim $MaxDays ; max days before expiration
Dim $MailTo , $MailSender , $MailServer ; mail parameters
Dim $BlatCmd ; Blat command string
$MaxDays = 10 ; passwords expiring within 10 days
; get array of user accounts
'Collecting'
$Members = GroupMembers(@DOMAIN , 'Domain Users' , 2 )
Chr (13 ) 'Reporting ' ?
$R = -1
; header
;00000000011111111112222222222333333333344444444445555555555666666666677777777778
;12345678901234567890123456789012345678901234567890123456789012345678901234567890
$Header = 'UserID UserName Locked? Expired?' + @CRLF
$Header = $Header + ' Expiration date' + @CRLF
$Header = $Header + '===============================================================================' + @CRLF
For Each $Member In $Members
; get specific user data
$objUser = GetObject ('WinNT://' + @DOMAIN + '/' +$Member + ',user' )
; read flags
$Flags = $objUser .UserFlags
; if not disabled, and not Never Expires, report on expired or about to expire accounts
If Not $objUser .AccountDisabled And Not ($Flags & 65536 )
$ExpDate = FixDate($objUser .PasswordExpirationDate)
$Days = Int (TimeDiff('Now' , $ExpDate , 'D' ))
$LStat = $objUser .IsAccountLocked
$EStat = $objUser .PasswordExpired
If $EStat Or $LStat Or $Days < 10
$R = $R + 1
ReDim Preserve $RptData [$R ]
$RptData [$R ] = Left ($Member + ' ' , 15 )
$RptData [$R ] = $RptData [$R ] + Left ($objUser .FullName + ' ' , 40 )
; display LOCKED and EXPIRED status
If $LStat
$RptData [$R ] = $RptData [$R ] + 'LOCKED '
Else
$RptData [$R ] = $RptData [$R ] + ' '
EndIf
If $EStat
$RptData [$R ] = $RptData [$R ] + 'EXPIRED ' + @CRLF + ' ' + $ExpDate
Else
; get remaining days
If $Days < $MaxDays
$RptData [$R ] = $RptData [$R ] + $Days + ' REMAIN ' + @CRLF + ' ' + $ExpDate
Else
$RptData [$R ] = $RptData [$R ] + ' '
EndIf
EndIf
If Exist ('.\debug.txt' )
$RptData [$R ] ?
$I = $I + 1
If $I > 100 Quit 0 EndIf
EndIf
EndIf
EndIf
Next
Del '%S_CONFIG%\Logs\ExpiredPW.txt' ; remove prior report
$R = RedirectOutput ('%S_CONFIG%\Logs\ExpiredPW.txt' ) ; create new report file
$Header ; output the header
For $R = 0 to UBound ($RptData )
If $R Mod 52 = 0 And $R > 0
Chr (12 ) $Header ; output a formfeed and header every 52 records
EndIf
$RptData [$R ] ?
Next
$R = RedirectOutput ('' ) ; close the report file
$MailTo = ReadProfileString ('%S_CONFIG%\lockout.ini' , 'MAIL' , 'MailTo' )
$MailSender = ReadProfileString ('%S_CONFIG%\lockout.ini' , 'MAIL' , 'MailSender' )
$MailServer = ReadProfileString ('%S_CONFIG%\lockout.ini' , 'MAIL' , 'MailServer' )
; send the report via email (BLAT)
If $MailTo <> ''
$BlatCmd = '%COMSPEC% /c %S_BIN%\blat.exe %S_CONFIG%\Logs\ExpiredPW.txt'
$BlatCmd = $BlatCmd + ' -to ' + $MailTo
$BlatCmd = $BlatCmd + ' -subject "Expiring Passwords"'
$BlatCmd = $BlatCmd + ' -f ' + $MailSender
$BlatCmd = $BlatCmd + ' -server ' + $MailServer
$BlatCmd = $BlatCmd + ' >NUL:'
Shell $BlatCmd
EndIf
Exit 0
; ================================================================================
; correct the date format - change from "11/1/2007 2:31:30 PM" to "2007/11/01 14:31:30"
Function FixDate($_Date )
Dim $_ODate
Dim $_Tmp
$_ODate = Split ($_Date , ' ' )
; Change the date format
$_Tmp = Split ($_ODate [0 ], '/' )
$_ODate [0 ] = $_Tmp [2 ] + '/' + Right ('0' + $_Tmp [0 ], 2 ) + '/' + Right ('0' + $_Tmp [1 ], 2 )
; Change the time format
$_Tmp = Split ($_ODate [1 ], ':' )
If $_ODate [2 ] = 'PM' And Val ($_Tmp [0 ]) < 12
$_Tmp [0 ] = Right ('0' + (Val ($_Tmp [0 ]) + 12 ), 2 )
Else
$_Tmp [0 ] = Right ('0' + $_Tmp [0 ], 2 )
EndIf
$_ODate [1 ] = Join ($_Tmp , ':' )
$FixDate = $_ODate [0 ] + ' ' + $_ODate [1 ]
Exit 0
EndFunction
;
;FUNCTION GroupMembers
;
;ACTION Returns an array of all group members of the specified group
;
;SYNTAX GroupMembers(Target, Group, [FLAG])
;
;PARAMETERS Target
; The Domain name or Workstation to work with. For faster workstation
; execution, include the Domain Name that the workstation is a meber of.
;
; "Kixtart/beanbag" would be working with the workstation Beanbag in the
; Kixtart domain
;
; Group
; The Group you want to query
;
; [FLAGS]
; To use the flags options add the numbers of the desired flags toghthers and
; Use that number in the flag field.
;
; Filter :(only one filter flag at a time please)
; 1 = all
; 2 = Users only
; 4 = Groups only
;
; ADSI Information(return ADSI information "pick only one")
; 8 = ADSPath field
; 16 = ADSI Object Handle
;
;RETURNS an array containing , if the ADSPath option is used the ADSPath
; will also be returned |.
;
;REMARKS ADSI com object must be installed.
;
;EXAMPLES ;this return all members of the Domain Admins group in the kixtart domain.
; $members = groupmembers("kixtart","Domain admins")
;
; ;this will will return all groups in the local administrators group on
; ;the Workstation beanbad in the kixtart domain. Also the
; $groups = groupmembers("kixtart/beanbag","Administratoos","group")
Function Groupmembers($target , $group , optional $flag )
DIM $temparray [8 ], $member , $i , $chunk , $flag , $ADSIFlag , $filterFlag
$chunk = ubound ($temparray )
$flag = val ($flag )
$i = 0
$group = getobject ("WinNT://" + $target + "/" + $group )
if vartype ($group ) <> 9 exit (@error ) endif
select
case $flag & 1
$filterflag = 1
case $flag & 2
$filterflag = 2
case $flag & 4
$filterflag = 4
case 1
$filterflag = 1
endselect
select
case $flag & 8
$ADSIFlag = 8
case $flag & 16
$ADSIFlag = 16
endselect
for each $member in $group .members
select
case $filterflag = 2 AND $member .class = "user"
if substr ($member .name,len ($member .name),1 ) <> Chr (36 )
$temparray [$i ] = $member .name
select
case $adsiflag = 8
$temparray [$i ] = $member .adspath
case $adsiflag = 16
$temparray [$i ] = $member
endselect
$i = $i + 1
endif
case $filterflag = 4 AND $member .class = "Group"
if substr ($member .name,len ($member .name),1 ) <> Chr (36 )
$temparray [$i ] = $member .name
select
case $adsiflag = 8
$temparray [$i ] = $member .adspath
case $adsiflag = 16
$temparray [$i ] = $member
endselect
$i = $i + 1
endif
case $filterflag = 1
if substr ($member .name,len ($member .name),1 ) <> Chr (36 )
$temparray [$i ] = $member .name
select
case $adsiflag = 8
$temparray [$i ] = $member .adspath
case $adsiflag = 16
$temparray [$i ] = $member
endselect
$i = $i + 1
endif
case $filterflag
;bit bucket
endselect
if $i = ubound ($temparray )
redim preserve $temparray [Ubound ($temparray )+$chunk ]
endif
next
if $i <> 0
redim preserve $temparray [$i -1 ]
$groupmembers =$temparray
endif
endfunction
;;
;;======================================================================
;;
;;FUNCTION TimeDiff()
;;
;;AUTHOR Glenn Barnas
;;
;;VERSION 2.2 / 2007/10/14
;; Modified to increase accuracy, permit fracional second calculations
;; 2.1 / 2007/03/17
;; added "now" and "today" options for both start and end times
;; 2.0 / 2006/11/20
;; Changes for code efficiency; added defaults for midnight
;;
;;ACTION Calculates the time difference between two given date/time strings
;;
;;SYNTAX TimeDiff(Start [, End] [, Format] [, MSec])
;;
;;PARAMETERS Start - REQUIRED, String value representing the start timestamp
;; Format yyyy/mm/dd hh:mm:ss
;;
;; End - OPTIONAL, Defaults to "now"
;; String value representing the ending time
;; Format yyyy/mm/dd hh:mm:ss
;; Can be the special value "now" for the current date/time, or "today"
;; for midnight of the current day.
;;
;; When the time value is not specified, it defaults to 00:00:00.000 (midnight)
;;
;; Format - OPTIONAL, one of:
;; "m" - return minutes
;; "h" - return hours
;; "d" - return days
;; "y" - return years
;; When a format value is specified, it returns the fractional part (ie 0.5 days for 12 hours).
;;
;; MSec - OPTIONAL, True if the fractional seconds should be returned. Default
;; is false, returning whole seconds, to maintain compatibility with earlier versions.
;; MSec only affects the return of fractional seconds, not fractional parts of other time formats.
;;
;;REMARKS Returns a value representing the difference in time between two date/time
;; strings. Assumes that "Start" is in the past, but will properly return a
;; negative value if it is in the future.
;;
;;RETURNS Double - difference between Start and End timestamps in seconds
;;
;;DEPENDENCIES None
;;
;;TESTED WITH Kix 4.2+, NT4, W2K, WXP, W2K3
;;
;;EXAMPLES If TimeDiff(GetFileTime('SomeFile.txt'), 'now', 'h') > 48
;; "File is more than 2 days old!" ?
;; EndIf
;
Function TimeDiff($_Start , OPTIONAL $_End , OPTIONAL $_Fmt , OPTIONAL $_MSec )
Dim $_ , $_SDate , $a_Start , $_EDate , $a_End , $_Duration
; Check for special START parameters
Select
Case $_Start = 'now'
$_Start = @DATE + ' ' + @TIME + '.' + @MSECS
Case $_START = 'today'
$_Start = @DATE + ' 00:00:00.000'
EndSelect
; Check for special END parameters
Select
Case $_End = 'now' Or $_End = ''
$_End = @DATE + ' ' + @TIME + '.' + @MSECS
Case $_End = 'today'
$_End = @DATE + ' 00:00:00.000'
EndSelect
; Validate parameters
; Parameters passed are "yyyy/mm/dd hh:mm:ss[.sss]" - make sure the default time is added
$a_Start = Split (Join (Split (Join (Split ($_Start + ' 00:00:00.000' , '/' ), ' ' ), ':' ), ' ' ), ' ' , 6 )
If UBound ($a_Start ) <> 5 Exit 87 EndIf ; bad start time parameter
For $_ = 0 to 5
$a_Start [$_ ] = CDbl ($a_Start [$_ ]) ; convert to numeric values
Next
$a_End = Split (Join (Split (Join (Split ($_End + ' 00:00:00.000' , '/' ), ' ' ), ':' ), ' ' ), ' ' , 6 )
If UBound ($a_End ) <> 5 Exit 87 EndIf ; bad start time parameter
For $_ = 0 to 5
$a_End [$_ ] = CDbl ($a_End [$_ ]) ; convert to numeric values
Next
; Convert dates to Days, then convert to seconds and add the time value
If $a_Start [1 ] < 3
$a_Start [1 ] = $a_Start [1 ] + 12
$a_Start [0 ] = $a_Start [0 ] - 1
EndIf
$_SDate = $a_Start [2 ] + ( 153 * $a_Start [1 ] - 457 ) / 5 + 365 * $a_Start [0 ] + $a_Start [0 ] / 4 - $a_Start [0 ] / 100 + $a_Start [0 ] / 400 - 306
$_SDate = CDbl ($_SDate ) * 86400.0
$_SDate = $_SDate + $a_Start [3 ] * 3600 + $a_Start [4 ] * 60 + $a_Start [5 ]
If $a_End [1 ] < 3
$a_End [1 ] = $a_End [1 ] + 12
$a_End [0 ] = $a_End [0 ] - 1
EndIf
$_EDate = $a_End [2 ] + ( 153 * $a_End [1 ] - 457 ) / 5 + 365 * $a_End [0 ] + $a_End [0 ] / 4 - $a_End [0 ] / 100 + $a_End [0 ] / 400 - 306
$_EDate = CDbl ($_EDate ) * 86400.0
$_EDate = $_EDate + $a_End [3 ] * 3600 + $a_End [4 ] * 60 + $a_End [5 ]
; Get the duration between the timestamps
$_Duration = CDbl ($_EDate - $_SDate )
; Trim fractional seconds if the MSec flag wasn't set
; Value returned is whole seconds
If Not $_MSec
$_Duration = CInt ($_Duration )
EndIf
; Return data as a Double - seconds (default), hours, minutes, days, or years
Select
Case $_Fmt = 'm' ; minutes
$TimeDiff = $_Duration / 60.0
Case $_Fmt = 'h' ; hours
$TimeDiff = $_Duration / 3600.0
Case $_Fmt = 'd' ; days
$TimeDiff = $_Duration / 86400.0
Case $_Fmt = 'y' ; years
$TimeDiff = $_Duration / 31536000.0
Case 1
$TimeDiff = $_Duration
EndSelect
Exit 0
EndFunction
_________________________
Actually I
am a Rocket Scientist!
Top
Moderator: Jochen , Allen , Radimus , Glenn Barnas , ShaneEP , Ruud van Velsen , Arend_ , Mart
0 registered
and 1044 anonymous users online.