Rich Rumble
asked on
Powershell script, specify domain
We've modified this Script to include a "ping" function since we have an unstable network at this time and are working on that separately. The current script assumes we want info about a user in the current domain, but we'd like to specify the domain, perhaps from a list like that found from issuing a "(Get-ADForest).domains" in PowerShell. Our PowerShell version is mostly 2.0, the windows 7 sp1 default. Commandlets or other scripting techniques should reflect this constraint. If possible I'd like it to also accept command line arg's beyond the username, like the domain then username.
.\FindUserBadPwdAttempts.p s1 domain_x user_x
or perhaps
.\FindUserBadPwdAttempts.p s1 domain_x\user_x
-------------------------- ---------- ---------- ---------- ----
if no args... (pseudo code)
Else
{
$ADdomain = Read-Host "Pick a domain: 1='$domain_a,' 2='$domain_b', 3='$domain_c'"
#something to that effect
-------------------------- ---------- ---------- ---------- ----
I can't seem to make it work, so I rolled back to this working script. Anyone want to take a stab at helping add the domain specification piece?
Thanks!
-rich
.\FindUserBadPwdAttempts.p
or perhaps
.\FindUserBadPwdAttempts.p
--------------------------
if no args... (pseudo code)
Else
{
$ADdomain = Read-Host "Pick a domain: 1='$domain_a,' 2='$domain_b', 3='$domain_c'"
#something to that effect
--------------------------
I can't seem to make it work, so I rolled back to this working script. Anyone want to take a stab at helping add the domain specification piece?
Thanks!
-rich
# FindUserBadPwdAttempts.ps1
# PowerShell Version 1 script to assist in troubleshooting accounts
# experiencing bad password attempts. It can also be used to investigate
# how accounts get locked out in Active Directory. The script finds
# the values of the sAMAccountName, pwdLastSet, lockoutTime, lastLogon,
# logonCount, badPwdCount, and badPasswordTime attributes for a specified
# user. The last 4 attributes are not replicated, so a different value is
# saved on every domain controller in the domain. A separate line of output
# is generated for each domain controller. The script prompts for either
# the distingished name or the sAMAccountName of an account.
# Author: Richard L. Mueller
# Version 1.0 - October 6, 2015
# Check for parameter identifying the object.
If ($Args.Count -eq 1)
{
$UserName = $Args[0]
}
Else
{
$UserName = Read-Host "Enter user sAMAccountName or distinguished name"
}
# Setup the DirectorySearcher object.
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.PageSize = 200
$Searcher.SearchScope = "subtree"
$Domain = New-Object System.DirectoryServices.DirectoryEntry
$BaseDN = $Domain.distinguishedName
If ($UserName -Like "*,*")
{
$Searcher.Filter = "(distinguishedName=$UserName)" #don't need this line for our needs
}
Else
{
$Searcher.Filter = "(sAMAccountName=$UserName)"
}
# Check for existence of the user object on any DC.
$Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$BaseDN"
$Check = $Searcher.FindOne()
If (-Not $Check)
{
Write-Host "Error: User $UserName not found" -foregroundcolor red
Break
}
# Specify the attribute values to retrieve.
$Searcher.PropertiesToLoad.Add("distinguishedName") > $Null
$Searcher.PropertiesToLoad.Add("sAMAccountName") > $Null
$Searcher.PropertiesToLoad.Add("badPwdCount") > $Null
$Searcher.PropertiesToLoad.Add("badPasswordTime") > $Null
$Searcher.PropertiesToLoad.Add("lockoutTime") > $Null
$Searcher.PropertiesToLoad.Add("logonCount") > $Null
$Searcher.PropertiesToLoad.Add("lastLogon") > $Null
$Searcher.PropertiesToLoad.Add("pwdLastSet") > $Null
$D = [system.directoryservices.activedirectory.Domain]::GetCurrentDomain()
$PDC= $D.PdcRoleOwner
# Output a heading line.
"sAMAccountName, pwdLastSet, lockoutTime, DC, lastLogon, logonCount, badPwdCount, badPasswordTime"
# Query every domain controller in the domain.
ForEach ($DC In $D.DomainControllers)
{
$ping = get-wmiobject -Query "select * from win32_pingstatus where Address='$DC'"
# Display Results
if ($ping.statuscode -eq 0) {
#"'$DC' responded in: {0}ms" -f $ping.responsetime
$Server = $DC.Name
$Result = $Null
# Identify the DC with the PDC Emulator role.
If ($Server -eq $PDC) {$ServerName = "$Server (PDCe)"}
Else {$ServerName = $Server}
# Specify the DC and domain in the Base of the query.
$Base = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$Server/$BaseDN"
$Searcher.SearchRoot = $Base
$Result = $Searcher.FindOne()
If ($Result)
{
# Retrieve the values.
$DN = $Result.Properties.Item("distinguishedName")
$NTName = $Result.Properties.Item("sAMAccountName")
$BadCount = $Result.Properties.Item("badPwdCount")
$LogonCount = $Result.Properties.Item("logonCount")
$Time = $Result.Properties.Item("badPasswordTime")
$Last = $Result.Properties.Item("lastLogon")
$Pwd = $Result.Properties.Item("pwdLastSet")
$Lock = $Result.Properties.Item("lockoutTime")
# Convert LargeInteger values into datetime values in the UTC zone.
If ($Time.Count -eq 0) {$BadTime = "Never"}
Else
{
If ($Time.Item(0) -eq 0) {$BadTime = "Never"}
Else {$BadTime = ([DateTime]$Time.Item(0)).AddYears(1600).ToUniversalTime()}
}
If ($Last.Count -eq 0) {$LastLogon = "Never"}
Else
{
If ($Last.Item(0) -eq 0) {$LastLogon = "Never"}
Else {$LastLogon = ([DateTime]$Last.Item(0)).AddYears(1600).ToUniversalTime()}
}
If ($Pwd.Count -eq 0) {$PwdLastSet = "Never"}
Else
{
If ($Pwd.Item(0) -eq 0) {$PwdLastSet = "Never"}
Else {$PwdLastSet = ([DateTime]$Pwd.Item(0)).AddYears(1600).ToUniversalTime()}
}
If ($Lock.Count -eq 0) {$Lockout = "Never"}
Else
{
If ($Lock.Item(0) -eq 0) {$Lockout = "Never"}
Else {$Lockout = ([DateTime]$Lock.Item(0)).AddYears(1600).ToUniversalTime()}
}
# Output in comma delimited format.
"$NTName,$PwdLastSet,$Lockout,$ServerName,$LastLogon,$LogonCount,$BadCount,$BadTime"
}
Else
{
Write-Host "ERROR: Failed to connect to DC $Server" -foregroundcolor red -backgroundcolor black
",,,$ServerName,,,,"
}
}
else {
"'$DC' did not respond"
}
}
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
Fixed it! Forgot the "dc=" in front of the $ADdomain...
$BaseDN = "'$ADdomain',DC=domain_x,D C=com"
vs
$BaseDN = "DC=$ADdomain,DC=domain_x, DC=com"
Thanks!
$BaseDN = "'$ADdomain',DC=domain_x,D
vs
$BaseDN = "DC=$ADdomain,DC=domain_x,
Thanks!
ASKER
Thanks for the help, finally figured out something for myself while I was at it!
ASKER
Had to make even more changes, turns out line 75 of the above script still overrode the specified, I've managed to work it out, I'm sure it's not the best way, but it's working!
# FindUserBadPwdAttempts.ps1
# PowerShell Version 1 script to assist in troubleshooting accounts
# experiencing bad password attempts. It can also be used to investigate
# how accounts get locked out in Active Directory. The script finds
# the values of the sAMAccountName, pwdLastSet, lockoutTime, lastLogon,
# logonCount, badPwdCount, and badPasswordTime attributes for a specified
# user. The last 4 attributes are not replicated, so a different value is
# saved on every domain controller in the domain. A separate line of output
# is generated for each domain controller. The script prompts for either
# the distingished name or the sAMAccountName of an account.
# Author: Richard L. Mueller
# Version 1.0 - October 6, 2015
[CmdletBinding()]
param(
[Parameter(Position=0,Mandatory=$false)]$Username
)
begin{
$IsUsernameWithBar= $Username -match "\\"
if($IsUsernameWithBar){
$array= $Username.split('\')
$Username=$array[1]
$ADdomain=$array[0]
}
$ADdomain = $ADdomain
$ADdomainDot= $ADdomain.psobject.copy()
}
process{
# Setup the DirectorySearcher object.
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.PageSize = 200
$Searcher.SearchScope = "subtree"
$Domain = New-Object System.DirectoryServices.DirectoryEntry
$BaseDN = "DC=$ADdomain,DC=domain_x,DC=COM"
$BaseDNdot = "$ADdomainDot.domain_x.COM"
$Searcher.Filter = "(sAMAccountName=$UserName)"
# Check for existence of the user object on any DC.
$Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$BaseDN"
$Check = $Searcher.FindOne()
If (-Not $Check)
{
Write-Host "Error: User $UserName not found" -foregroundcolor red
Break
}
# Specify the attribute values to retrieve.
$Searcher.PropertiesToLoad.Add("distinguishedName") > $Null
$Searcher.PropertiesToLoad.Add("sAMAccountName") > $Null
$Searcher.PropertiesToLoad.Add("badPwdCount") > $Null
$Searcher.PropertiesToLoad.Add("badPasswordTime") > $Null
$Searcher.PropertiesToLoad.Add("lockoutTime") > $Null
$Searcher.PropertiesToLoad.Add("logonCount") > $Null
$Searcher.PropertiesToLoad.Add("lastLogon") > $Null
$Searcher.PropertiesToLoad.Add("pwdLastSet") > $Null
$DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext("Domain", $BaseDNdot)
$D = [system.directoryservices.activedirectory.Domain]::GetDomain($DomainContext)
$PDC= $D.PdcRoleOwner
# Output a heading line.
"SamAccountName, PwdLastSet, LockoutTime, DC, DC IP, LastLogon, LogonCount, BadPwdCount, BadPasswordTime"
# Query every domain controller in the domain.
ForEach ($DC In $D.DomainControllers)
{
$ping = get-wmiobject -Query "select * from win32_pingstatus where Address='$DC'"
# Display Results
if ($ping.statuscode -eq 0) {
#"'$DC' responded in: {0}ms" -f $ping.responsetime
$Server = $DC.Name
$IPAddress = $DC.IPAddress
$Result = $Null
# Identify the DC with the PDC Emulator role.
If ($Server -eq $PDC) {$ServerName = "$Server (PDCe)"}
Else {$ServerName = $Server}
# Specify the DC and domain in the Base of the query.
$Base = New-Object System.DirectoryServices.DirectoryEntry "LDAP://$Server/$BaseDN"
$Searcher.SearchRoot = $Base
$Result = $Searcher.FindOne()
If ($Result)
{
# Retrieve the values.
$DN = $Result.Properties.Item("distinguishedName")
$NTName = $Result.Properties.Item("sAMAccountName")
$BadCount = $Result.Properties.Item("badPwdCount")
$LogonCount = $Result.Properties.Item("logonCount")
$Time = $Result.Properties.Item("badPasswordTime")
$Last = $Result.Properties.Item("lastLogon")
$Pwd = $Result.Properties.Item("pwdLastSet")
$Lock = $Result.Properties.Item("lockoutTime")
# Convert LargeInteger values into datetime values in the UTC zone.
If ($Time.Count -eq 0) {$BadTime = "Never"}
Else
{
If ($Time.Item(0) -eq 0) {$BadTime = "Never"}
Else {$BadTime = ([DateTime]$Time.Item(0)).AddYears(1600).ToUniversalTime()}
}
If ($Last.Count -eq 0) {$LastLogon = "Never"}
Else
{
If ($Last.Item(0) -eq 0) {$LastLogon = "Never"}
Else {$LastLogon = ([DateTime]$Last.Item(0)).AddYears(1600).ToUniversalTime()}
}
If ($Pwd.Count -eq 0) {$PwdLastSet = "Never"}
Else
{
If ($Pwd.Item(0) -eq 0) {$PwdLastSet = "Never"}
Else {$PwdLastSet = ([DateTime]$Pwd.Item(0)).AddYears(1600).ToUniversalTime()}
}
If ($Lock.Count -eq 0) {$Lockout = "Never"}
Else
{
If ($Lock.Item(0) -eq 0) {$Lockout = "Never"}
Else {$Lockout = ([DateTime]$Lock.Item(0)).AddYears(1600).ToUniversalTime()}
}
# Output in comma delimited format.
"$NTName, $PwdLastSet, $Lockout, $ServerName, $IPAddress, $LastLogon, $LogonCount, $BadCount, $BadTime"
}
Else
{
Write-Host "ERROR: Failed to connect to DC $Server" -foregroundcolor red -backgroundcolor black
", , , $ServerName, $IPAddress, , ,"
}
}
else {
", , , $DC, Ping Failed, , ,"
}
}
}
ASKER
(cmd line is now -addomin instead of -domain)
Open in new window