<# Get-UserLockoutStatus.ps1 This script runs interactively to get lockout information on all domain controllers Alan Kaplan 7/2/2018 version 1.0 7/23/2018 version 1.1 allows check of bad password if account not locked. 9/15/2018 version 1.2 notification if no lockouts found #> #Requires -module ActiveDirectory #do not edit False because we don't need $PS variables $PSDisableSerializationPreference = $False Add-Type -assemblyname Microsoft.visualBasic Function Search-LockedUsers { Write-host "Searching for locked user info on $dom DCs." -ForegroundColor Green $AllLocked = Search-ADAccount -UsersOnly -LockedOut -Server $dom | Select-Object Name, SamAccountName, Enabled, PasswordExpired, PasswordNeverExpires, AccountExpirationDate, DistinguishedName if ($AllLocked.count -eq 0){ $retval = [Microsoft.VisualBasic.Interaction]::msgbox("No locked out users found", 'okonly,Information', "$dom`: No Lockouts") Exit } $AllLocked|Out-GridView -Title "Select Locked Account(s) to check" -PassThru } Function Get-LockedUserName { $msg = "This script identifies locked out users with an AD query. Elevated permissions are not required.`nEnter user identity in $dom" $id = [Microsoft.VisualBasic.Interaction]::inputbox($msg, "User Identity", '') if ($id -eq '' ) {exit} Try { $u = get-aduser -Server $dom -Identity $id -property lockedout -ErrorAction Stop } Catch { [Microsoft.VisualBasic.Interaction]::msgbox($Error[0].exception.message, 'okonly,Exclamation', 'User Account Error') | Out-Null exit } if (!$u.lockedout) { $msg = "$id is not locked. Do you want to:`n1) Continue to view bad password count`n2) Quit " $retval = [Microsoft.VisualBasic.Interaction]::inputbox($msg, "Continue?", 2) switch ($retval) { 2 {Exit} Default {} } } $u } workflow Get-UserLockoutWorkFlow { param( $DCs2Check, $TargetUserNames, $PDC) Write-Progress "Searching for locked user info on $dom DCs." ForEach ($DC in $DCs2Check) { InlineScript { $pdc = $using:PDC $dcName = $using:DC $userList = $using:TargetUserNames Foreach ($user in $UserList) { $props = @{ identity = $user Server = $using:DC Properties = "Description,LockedOut,badPwdCount,LastBadPasswordAttempt,PasswordLastSet,AccountLockoutTime".Split(',') ErrorAction = 'Stop' } #The select statement came mostly from another script on the web Get-ADUser @props | Select-Object Name, Description, @{Label = "SamAccountName"; Expression = {$user}}, @{Label = "DC Name"; Expression = {$DCName}}, @{Label = "PDC"; Expression = {if ($DCName -eq $pdc) {$true}ELSE {$false}}}, @{Label = "User State"; Expression = {If ($_.LockedOut -eq 'True') {'Locked'} Else {'Not Locked'}}}, @{Label = "Bad Pwd Count"; Expression = {If (($_.badPwdCount -eq '0') -or ($null -eq $_.badPwdCount)) {'0'} Else {$_.badPwdCount}}}, @{Label = "Last Bad Pwd"; Expression = {If ($null -eq $_.LastBadPasswordAttempt) {'None'} Else {$_.LastBadPasswordAttempt}}}, @{Label = "Pwd Last Set"; Expression = {If ($null -eq $_.PasswordLastSet) {'Password Must Change'} Else {$_.PasswordLastSet}}}, @{Label = "Lockout Time"; Expression = {If ($null -eq $_.AccountLockoutTime) {'N/A'} Else {$_.AccountLockoutTime}}} } } } Write-Progress "Done" -Completed } Write-Host "Enter domain name in input box" -ForegroundColor Green $myDom = ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).name $Dom = [Microsoft.VisualBasic.Interaction]::inputbox("Enter domain to search for locked accounts", "Domain", $myDom) if (!$dom) {Exit} Clear-Host Try { $PDC = (Get-ADDomain -Server $dom).PDCEmulator } Catch { $retval = [Microsoft.VisualBasic.Interaction]::msgbox($Error[0].exception.message, 'okonly,Exclamation', "$dom`: Domain Error") Exit } $msg = @" Do you want to: 1) Specify a user 2) Search locked users for $dom and choose from list 3) Quit "@ $retval = [Microsoft.VisualBasic.Interaction]::inputbox($msg, "Search or Specify", '') switch ($retval) { 1 {$targetUserNames = Get-LockedUserName; break} 2 {$targetUserNames = Search-LockedUsers; break} Default {exit} } if (!$targetUserNames) {Exit} Write-Host "Getting information for selected account(s)" -ForegroundColor Green # Connect to the specified domain and retrieve the list of all dcs within this domain $DomainContext = new-object System.directoryServices.ActiveDirectory.DirectoryContext("Domain", $Dom) $ADSIDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) $DCList = ($ADSIDomain.DomainControllers).name $msg = "Lock out information (selected items copied to clipboard). Note the PDC Emulator will have a copy of the highest count" Get-UserLockoutWorkFlow -DCs2Check $DCList -TargetUserName ($targetUserNames).samAccountName -PDC $PDC | Select-Object * -ExcludeProperty PS* | Sort-Object SamAccountName | Out-GridView -Title $msg -PassThru | clip write-Host "Done" -ForegroundColor Green