On Error Resume Next
' Account_Bulk_Unlock.vbs will search Active Directory for locked accounts and bulk unlock them.
' Also supports a /readonly switch which will only report on locked accounts and not unlock them.
' http://blog.techscrawl.com - 15 SEP 2008 - CNS.

' Routine called to force cscript engine instead of wscript
sub force_cscript
    dim args : args=""
    dim i, wshshell
    If right(lCase(wscript.fullname),11)= "wscript.exe" then
        for i=0 to wscript.arguments.count-1
            args = args & wscript.arguments(i) & " "
        next
        set wshshell=CreateObject("wscript.shell")
        wshshell.run wshshell.ExpandEnvironmentStrings("%comspec%") & _
            " /c cscript.exe //nologo " & wscript.scriptfullname & " " & args
        set wshshell=nothing
        wscript.quit
    end if
end sub

'Force a cscript host
force_cscript

argCount = WScript.Arguments.Count

If argCount > 0 Then
    passedArg = Wscript.Arguments(0)
Else
    passedArg = "NullValuePassed"
End If

str1 = "/?"
str2 = "/help"
str3 = "/readonly"
str4 = "NullValuePassed"

intCompare1 = StrComp(passedArg, str1, vbTextCompare)
intCompare2 = StrComp(passedArg, str2, vbTextCompare)
intCompare3 = StrComp(passedArg, str3, vbTextCompare)
intCompare4 = StrComp(passedArg, str4, vbTextCompare)

If (intCompare3 = 0 or intCompare4 = 0) Then

' Setup ADO objects

Set adoCommand = CreateObject("ADODB.Command")
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Open "Active Directory Provider"
adoCommand.ActiveConnection = adoConnection
Set objShell = WScript.CreateObject("WScript.Shell")
workingDir = objShell.CurrentDirectory
numAcctsUnlocked = 0
numAcctsVisited = 0
numFoundLocked = 0

' Create Log File
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objLogFile = objFS.CreateTextFile("Acct_Unlock_Log.txt")


' Search Active Directory domain

Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
strBase = "<LDAP://" & strDNSDomain & ">"
Set objSystemInfo = CreateObject("ADSystemInfo")
strDomain = objSystemInfo.DomainShortName

' Filter on user objects
strFilter = "(&(objectCategory=person)(objectClass=user))"

' Comma delimited list of attribute values to retrieve
strAttributes = "sAMAccountName,cn"

' 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

WScript.Echo "---------STARTING JOB----------------------------------"
WScript.Echo "Searching for locked accounts in domain: " & strDomain
WScript.Echo "-------------------------------------------------------" & VbCrLf

objLogFile.WriteLine "---------STARTING JOB----------------------------------"
objLogFile.WriteLine "Searching for locked accounts in domain: " & strDomain
objLogFile.WriteLine "Started: " & Date & " " & Time
objLogFile.WriteLine "-------------------------------------------------------" & VbCrLf

' Run the query.
Set adoRecordset = adoCommand.Execute

' Enumerate the resulting recordset.
Do Until adoRecordset.EOF

' Retrieve values
strUserName = adoRecordset.Fields("sAMAccountName").Value
strCN = adoRecordset.Fields("cn").value
set objUser = GetObject("WinNT://" & strDomain & "/" & strUsername)

if objUser.IsAccountLocked = TRUE then
numFoundLocked = numFoundLocked + 1

' Read-only
If intCompare3 = 0 Then
WScript.Echo "Account Locked: " & strUserName
objLogFile.WriteLine "ACCOUNT LOCKED: " & strUserName
Else

' Perform account unlock
objUser.IsAccountLocked = FALSE
objUser.SetInfo
WScript.Echo "Account Unlocked: " & strUserName
objLogFile.WriteLine "ACCOUNT UNLOCKED: " & strUserName
numAcctsUnlocked = numAcctsUnlocked + 1
End If

else

objLogFile.WriteLine "Account Not Locked: " & strUserName

end if

numAcctsVisited = numAcctsVisited + 1

' Move to the next record in the recordset.
adoRecordset.MoveNext

Loop

' Summary
WScript.Echo VbCrLf & "---------JOB COMPLETE---------"
WScript.Echo "Total Accounts Examined: " & numAcctsVisited
WScript.Echo "Total Found Locked: " & numFoundLocked
WScript.Echo "Total Accounts Unlocked: " & numAcctsUnlocked
WScript.Echo "------------------------------"

objLogFile.WriteLine VbCrLf & "---------JOB COMPLETE---------"
objLogFile.WriteLine "Total Accounts Examined: " & numAcctsVisited
objLogFile.WriteLine "Total Found Locked: " & numFoundLocked
objLogFile.WriteLine "Total Accounts Unlocked: " & numAcctsUnlocked
objLogFile.WriteLine "------------------------------"

' Clean up
adoRecordset.Close
adoConnection.Close
objLogFile.Close

WScript.Echo VbCrLf & "LOGFILE: " & workingDir & "\Acct_Unlock_Log.txt."

ElseIf (intCompare1 = 0 or intCompare2 = 0) Then
    WScript.Echo "Bulk Unlocks Locked Active Directory Accounts." & VbCrLf
    WScript.Echo "Must be run under credentials with permission to unlock accounts." & VbCrLf
    WScript.Echo "/? or /help    Displays this help screen"
    WScript.Echo "/readonly    Reports on, but does not unlock, locked accounts"
    WScript.Echo "No Arguments    Run with no args, script will unlock accounts." & VbCrLf
Else
    WScript.Echo "Invalid switch. Try /help" & VbCrLf
End If

WScript.Echo "Press the ENTER key to exit..."
WScript.stdin.Read(1)