Number of Locked Users in AD

If you have information, script, utility, or idea that can be useful for HostMonitor community, you welcome to share information in this forum.
Post Reply
Kris
Posts: 375
Joined: Wed May 12, 2010 3:22 am

Number of Locked Users in AD

Post by Kris »

The following vBscript will give you the number of locked users on your domain.
You can create a test around it to monitor issues with... well... locking accounts 8)
It's quick & dirty, please modify to your situation.

Code: Select all

Set Domain = GetObject("WinNT://<YourDomain>")
Domain.Filter = Array("User")
    For Each UserObj In Domain
        If UserObj.IsAccountLocked = True Then
            Counter = Counter + 1
        End If
    Next
WScript.StdOut.Write "ScriptRes:Ok:" & Counter
SplanK
Posts: 38
Joined: Wed Nov 21, 2007 1:33 pm

Post by SplanK »

I have used this and created a Active script.

It reports good if there are 0 lock outs.
It reports bad if there are >0 lock outs as well as the accounts locked out.

Code: Select all

Option Explicit
const statusAlive       = "Host is alive:"
const statusDead        = "No answer:"
const statusUnknown     = "Unknown:"
const statusNotResolved = "Unknown host:"
const statusOk          = "Ok:"
const statusBad         = "Bad:"
const statusBadContents = "Bad contents:"

Call PerformTest()

FUNCTION PerformTest()
	dim Domain, Counter, UserObj, oLockedoutUser

	Set Domain = GetObject("WinNT://DOMAINNAME") 
	Counter = 0
	Domain.Filter = Array("User") 
	
	For Each UserObj In Domain 
		If UserObj.IsAccountLocked = True Then 
			
			If Counter = 0 Then
				oLockedoutUser = UserObj.Name
			else
				oLockedoutUser = oLockedoutUser & " / " & UserObj.Name
			end If
			
			Counter = Counter + 1 
			
		End If 
	Next 
		
	If Counter > 0 Then
		PerformTest = statusBad+"Locked Out users: " & Counter & " -> " & oLockedoutUser
	Else
		PerformTest = statusOk+"Locked Out users: " & Counter
	End If
End Function
Kris
Posts: 375
Joined: Wed May 12, 2010 3:22 am

Post by Kris »

Good job SplanK!

I had that one on my ToDo list.
You made it easy 8)

Thanks!
peterjwest
Posts: 17
Joined: Mon Jul 28, 2008 4:20 am

Post by peterjwest »

Hi,

Nice work - and big thanks to previous posters as the previous scripts gave me a little inspiration.

The only problem I had with the previous versions of the script was that it took a long time to run for me. This is because it enumerates every object in the domain and that can take time.

This lead me to making a modified version which uses an LDAP query to only pull locked accounts which are also enabled. I've included the script below.

The script takes a single mandatory parameter which is the domain to check in DNS format (i.e. contoso.com, uk.contoso.com etc.). If you wish you can also save the script as a regular .vbs file and adding /view onto the end of the parameters will also show the list of locked accounts.

Example syntax:
Just show the count: cScript.exe ScriptName.vbs contoso.com
Show the list too: cScript.Exe ScriptName.vbs contoso.com /view

Code: Select all

Option Explicit

'Define required variables
Dim objConnection
Dim iX
Dim objCommand
Dim objRecordSet
Dim sRetVal
Dim arrAttribute
Dim iDaysSinceDisabled
Dim iCount
Dim sDomain
Dim bListAccounts
Dim arrAccounts

'Define constants
const statusAlive       = "scriptRes:Host is alive:"
const statusDead        = "scriptRes:No answer:"
const statusUnknown     = "scriptRes:Unknown:"
const statusNotResolved = "scriptRes:Unknown host:"
const statusOk          = "scriptRes:Ok:"
const statusBad         = "scriptRes:Bad:"
const statusBadContents = "scriptRes:Bad contents:"

'Initialise the array
Redim arrAccounts(2,0)

'Get the parameters
sDomain = wScript.Arguments(0)
sDomain = GetNCFromDNSDomain(sDomain)

'If there are more parameters then...
If wScript.Arguments.Count >=2 Then
	
	'If the second argument is /view
	If LCase(wScript.Arguments(1)) = "/view" Then bListAccounts = True
End If
	
'Define required constants
Const ADS_SCOPE_SUBTREE = 2
Const ADS_CHASE_REFERRALS_ALWAYS = &H60

'Make the objects and configure them
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand =   CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"

'Define the query and load into the command object
Set objCommand.ActiveConnection = objConnection

'Query the appropriate OU for objects that are still disabled; this is deliberate to stop accounts which have been re-enabled but not moved from being deleted
objCommand.CommandText = "<LDAP://" & sDomain & ">;(&(objectCategory=Person)(objectClass=User)(lockoutTime>=1)(!userAccountControl:1.2.840.113556.1.4.803:=2));samAccountName,Name;Subtree"
objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 
objCommand.Properties("Chase Referrals") =&H60

'Run the query
Set objRecordSet = objCommand.Execute

'Loop through the results
Do While Not objRecordSet.EOF
		
	'If the option to list was given then load values into the array
	If bListAccounts Then
		arrAccounts(0,UBound(arrAccounts,2)) = objRecordset.Fields(0)
		arrAccounts(1,UBound(arrAccounts,2)) = objRecordset.Fields(1)
		arrAccounts(2,UBound(arrAccounts,2)) = objRecordset.Fields(2)
		Redim Preserve arrAccounts(2,UBound(arrAccounts,2)+1)
	End If
	
	'Increment the counter
	iCount = iCount+ 1
	
	'Move to the next record
	objRecordset.MoveNext
Loop

'Display the results
wScript.StdOut.Write statusOk & iCount

'If the option to view the locked accounts was given then...
If bListAccounts Then
	wScript.Echo ""
	wScript.Echo "SAM Account Name         Name"
	For iX=0 To UBound(arrAccounts,2)
		wScript.Echo PadString(arrAccounts(0,iX),25) & arrAccounts(1,iX)
	Next
End If

'End the script
wScript.Quit

Function GetNCFromDNSDomain(sDNSDomain)

	'Define required variables
	Dim sRetVal
	Dim arrParts
	Dim objItem
	
	'If there are periods in the string then...
	If Instr(sDNSDomain,".") > 0 Then
		
		'Split by the full stops
		arrParts = Split(sDNSDomain,".")
		
		'Loop through and build the string
		For Each objItem In arrParts
			sRetVal = sRetVal & "dc=" & objItem & ","
		Next
		
		'Strip the final ,
		sRetVal = Left(sRetVal,Len(sRetVal)-1)
	
	End If
	
	'Return the value
	GetNCFromDNSDomain = sRetVal
			
End Function

Function PadString(sString,iLen)

	'Define required variables
	Dim sRetVal
	
	'If the length is less than needed then pad with spaces
	If Len(sString) < iLen Then
		sRetVal = sString & String(iLen-Len(sString)," ")
	Else
		'If it's too long then chop it
		If Len(sString) > iLen Then
			sRetVal = Left(sString,iLen)
		Else
			'Otherwise just pass it back
			sRetVal = sString
		End If
	End If
	
	'Return the value
	PadString = sRetVal
	
End Function
Post Reply