Reputation: 13
I would like to query all AD users and get the following attributes from each user:
SamAccountName, UserPrincipalName, LastLogonDate, Enabled, LockedOut, PasswordNeverExpires, CannotChangePassword, whenCreated
As the domain has more than one domain controller I also want to make sure I get all the data. Any thoughts?
Many thanks
Here my code:
$domainControllers = Get-ADDomainController -Filter * | Select-Object -ExpandProperty Name
Write-Host "Create AD user report accross the following domaincontroller: $domaincontrollers"
# Create an empty array to store the results
$results = @()
$searchbase= "DC=XXX,DC=XX"
# Iterate through each domain controller and retrieve users
foreach ($dc in $domainControllers) {
$users = Get-ADUser -Filter * -SearchBase $Searchbase -Properties SamAccountName, UserPrincipalName, LastLogonDate, Enabled, LockedOut, PasswordNeverExpires, CannotChangePassword, whenCreated |
Select-Object SamAccountName, UserPrincipalName, @{Name="LastLogin"; Expression={$_.LastLogonDate}}, Enabled, LockedOut, PasswordNeverExpires, CannotChangePassword , whenCreated
$results += $users
# Export the results to a CSV file
}
$resultfinal = $results | Select-Object * -Unique
$resultfinal| Export-Csv -Path c:\logging\data\AD_User_Report.csv -NoTypeInformation
However often I simply get nothing back and I'm not sure why exactly. Probably it's related the "unique" sorting option?
Based on the domain spot checks (attribut editor) every user object would have the lastlogonDate so the domain schema should be up-to-date.
Upvotes: 1
Views: 11362
Reputation: 1
Try this, It worked for me.
# Get domain controllers and display the names
$domainControllers = Get-ADDomainController -Filter * | Select-Object -ExpandProperty Name
Write-Host "Create AD user report across the following domain controllers: $($domainControllers -join ', ')"
# Create an empty array to store the results
$results = @()
# Set the search base
$searchBase = "DC=XXX,DC=XXX"
# Iterate through each domain controller and retrieve users
foreach ($dc in $domainControllers) {
try {
$users = Get-ADUser -Filter * -SearchBase $searchBase -Properties SamAccountName, UserPrincipalName, LastLogonDate, Enabled, LockedOut, PasswordNeverExpires, CannotChangePassword, whenCreated -Server $dc |
Select-Object SamAccountName, UserPrincipalName, @{Name="LastLogin"; Expression={$_.LastLogonDate}}, Enabled, LockedOut, PasswordNeverExpires, CannotChangePassword, whenCreated
$results += $users
} catch {
Write-Host "Error occurred while retrieving users from domain controller $($dc): $_"
}
}
# Check if there are any results
if ($results.Count -eq 0) {
Write-Host "No users found in the specified search base."
} else {
# Export the results to a CSV file
$resultFinal = $results | Select-Object * -Unique
$resultFinal | Export-Csv -Path "c:\Temp\AD_User_Report.csv" -NoTypeInformation
}
Upvotes: 0
Reputation: 74
Here is a snippet of the code I used. It queries each domain controller and records the most recent logon time found between all the controllers. My domain only has three controllers so the code finished quickly.
#gets a list of domain controllers
$dcs = Get-ADDomainController -Filter {Name -like "*"}
#list of users including specied properties
$users = Get-ADUsers -Properties name, description, enabled , Department, CanonicalName, userPrincipalName
$result =@()
#loops through each user and then each domain controller
foreach($user in $users)
{
$time = 0
$License = "No Email"
foreach($dc in $dcs)
{
# queries the dc for the user last reprted logon time
$currentUser = Get-ADUser $user | Get-ADObject -Server $dc.HostName -Properties lastlogon
#checks if the logon time from the dc is more recent than the logon time from previous dc. If it is then $time is set to the current dc logon time for the user.
#A user will return 0 on a controller if they have never logged in using the dc.
if($currentUser.LastLogon -gt $time)
{
$time = $currentUser.LastLogon
# Converts the last logon time returned from the dc to a human readable format. The code will return a very old date if $time = 0
if($time -ne "0")
{
$dt = [DateTime]::FromFileTime($time)
$currentdc = $dc.Hostname
}
}
}
Finally I put all the data in a pscustomobect and exported that to excel
Upvotes: 0
Reputation: 989
In a big environment this will not be very performant. Querying all domain controllers to get the "complete" data can be misleading, because what happens when you delete a user in one domain controller, but it has not replicated yet? That user would be added to the list in your script.
I recommend query only one domain controller (force a replication via script beforehand if necessary). Skip the "Select-Object -Unique" altogether.
Upvotes: 0