6 min read
Boost your IT automation efficiency with new ScriptRunner release
We have just released our latest ScriptRunner update, version 7.1, packed with powerful new features aimed at making IT...
ScriptRunner Blog
Are you in charge of a directory service like AD or Azure AD? Then you must have spent quite a bit of time troubleshooting already. Fortunately, there is a way to make every administrator's life easier.
Directories provide a source of truth for organizations' identity management, whether the directory service is provided by Active Directory (AD) or Azure AD (AAD) and troubleshooting or identifying issues is a key task that must be performed by those in charge of the directory. Utilizing the right tool (or tools) can help make this task manageable and scripting (PowerShell or otherwise) has proven to be a useful tool for this type of task.
In this article, we'll explore how we can use PowerShell in troubleshooting common issues in Active Directory. It is worth noting that not everything needed to troubleshoot AD issues can be done with PowerShell directly, however, we can use PowerShell to place a 'wrapper' around other processes and utilize PowerShell to pull data for successful troubleshooting.
A common mistake made with site-to-site replication links is to correct a replication problem with a manual link instead of relying on the AutoGenerated ones that KCC ( Acronym! ) creates. Manual links do not get auto updated or work well with topology changes thus identifying manually created links can be good for a healthy environment.
With the following, we can list all AD replication links, with their GUID, To and From servers and if the link is AutoGenerated:
Get-ADReplicationConnection -Filter * |
Select-Object -Property Name, AutoGenerated, ReplicateFromDirectoryServer, ReplicateToDirectoryServer |
ForEach-Object {
$From = $_.ReplicateFromDirectoryServer
$To = $_.ReplicateToDirectoryServer
$_.ReplicateFromDirectoryServer = (($From -Split ',')[1] -Split '=')[1]
$_.ReplicateToDirectoryServer = (($To -Split ',')[0] -Split '=')[1]
Return $_
}
If one or more links had a value of 'False' for AutoGenerated, an investigation into why this was created should be performed. There may be a valid reason for it, although it would not be supported by Microsoft.
In addition to Site Links, checking the replication that transverses those links can be a critical component of AD troubleshooting. In this section we will explore some ways to use PowerShell as a wrapper around native Windows tools in order to examine the communication between Domain Controllers (DC) in an environment. The tools used in this section are dsquery, repadmin and dcdiag. With PowerShell we can export the results of these tools to an output file for analysis by a knowledgeable AD administrator.
Our first tool is dsquery which is used to query information with in AD and specifically in this case we are querying just Domain Controllers in AD. More on this one-liner can be found in Microsoft Docs.
'dsquery server -o rdn'
The tool repadmin can be used to expose some of the deeper replication issues that can occur between DCs, both inbound and outbound. Repadmin can reveal critical issues with DCs no longer able to replicate, identify topology issues and more. Below is a good core set of cmdlets that can be run from a PowerShell script. Note that each line exports results to a file to be examined:
$ADCmdletDestination = 'ADReplicationOutput.txt '
Check replication for all servers, cross all sites
C:\Windows\System32\repadmin.exe /syncall /e >> $ADCmdletDestination
Check Naming Context Replication
C:\Windows\System32\repadmin.exe /syncall /A >> $ADCmdletDestination
Sync using DN and not GUID DNS
C:\Windows\System32\repadmin.exe /syncall /d >> $ADCmdletDestination
Concise Replication Summary
C:\Windows\System32\repadmin.exe /replsummary * >> $ADCmdletDestination
Forces KCC to recalculate topology
C:\Windows\System32\repadmin.exe /kcc * >> $ADCmdletDestination
Shows last AD backup
C:\Windows\System32\repadmin.exe /showbackup * >> $ADCmdletDestination
Checks replication status for last inbound replication
C:\Windows\System32\repadmin.exe /showrepl * >> $ADCmdletDestination
Displays any inbound queued requests
C:\Windows\System32\repadmin.exe /queue * >> $ADCmdletDestination
Checks AD Bridgehead servers for issues
C:\Windows\System32\repadmin.exe /bridgeheads * /verbose >> $ADCmdletDestination
Returns Intersite Topology Generator (ISTG) server
C:\Windows\System32\repadmin.exe /istg * /verbose >> $ADCmdletDestination
"A list of the entries in the DS Bind cache."
C:\Windows\System32\repadmin.exe /showoutcalls * >> $ADCmdletDestination
Lists KCC Failures
C:\Windows\System32\repadmin.exe /failcache * >> $ADCmdletDestination
Lists known AD trusts
C:\Windows\System32\repadmin.exe /showtrust * >> $ADCmdletDestination
Displays replication features for a DC
C:\Windows\System32\repadmin.exe /bind * >> $ADCmdletDestination
In general, if there are issues, these commands should show something that is not correct. For example, if a DC's time is off, the replication summary will show synchronization errors. We may even see a DC that has been Tombstoned because it has not replicated within the configured Tombstone time limit. Event log error messages will also be discovered and help with root cause analysis.
Example from the /replsummary switch
With the tool dcdiag, we can run a series of Domain Controller tests which will help determine the relative help of each DC. The below one-liner will run all dcdiag tests as described here [/c], executes the tests for all DCs, no matter the Site it is in [/e] and uses verbose output [/v]. Note that the output from the command is also exported to a file for analysis. Keep in mind that in larger environments, this may take time to run and also to analyze the exported results.
dcdiag /c /e /v >> $ADCmdletDestination
Sample screen output
In the meantime, there are some direct replacements for these tools within PowerShell, however, at the time of writing this article, these cmdlets provide a more in-depth view of AD replication for troubleshooting purposes.
DNS is important to Active Directory health and administrators can test their DNS server with a few tools. With native PowerShell, we have a 'Test-DNSServer' cmdlet which is rather limited but can provide a quick test of a particular DNS server.
Sample 'Test-DnsServer' cmdlet
However, to dive a bit deeper, we can use PowerShell to execute Windows tools to dive deeper from DNSLint to dcdiag, as these tools are still valid even with PowerShell.
$DC = Get-ADDomainController $Env:ComputerName
$IPs = @()
$IPs = $DC.IPv4Address
$Server = $IPs[0]
$DNSLint = .\DNSLint.exe /ad $Server /s $Server /r dnslint /no_open /y
For even more information, we can use dcdiag to test DNS server functionality.
Sample DNSLint error report
Function GetInfo {
DCDiag /s:$DC /Test:dns /v /q /i /x:$DNSXMLDestination
$Data = @($DC,$Domain,$Site)
$Xml = $DNSXMLDestination
[Xml]$DCDiag = Get-Content $xml
$Summary = $dcdiag.DCDIAGTestResults.DNSEnterpriseTestResults.Summary.Domain.DC.test
Foreach ($line2 in $summary) {
$Data += @($Line2.Status)
}
$Rowline = $Data -join ","
Add-Content $DNSDestination $Rowline
$Rowline = $Null
}
# Main Script Body
$DNSDestination = 'DNSTestResults.csv'
$DNSXMLDestination = 'DNSTestResults.xml'
$Rows = "DC," + "Domain," + "Site," + "Auth," + "Basc," + "Forw," + "Del," + "Dyn," + "Rreg," + "Ext"
Add-Content -Path $DNSDestination $Rows
$Domains = (Get-ADForest).Domains
Foreach ($Domain in $Domains) {
$DomainControllers = Get-ADDomainController -Server $Domain -Filter *
Foreach ($Line in $DomainControllers) {
$Dc = $Line.HostName
$Domain = $Line.Domain
$Site = $Line.Site
GetInfo
}
}
Using both of these scripts, we can now get a picture of DNS and by reviewing the logs, the DNS infrastructure can be validated.
Sample DCDiag results file
A domain controller with DHCP enabled or with too many gateways can cause all sorts of issues with replication, user authentication as well as application problems. Having a good grasp of how each server is configured can help an administrator track down an issue with their domain controllers. The below script will look at each Network Interface Card (NIC) on a server and report back properties for validation:
# Variables
$Rows = 'Computer,' + 'IPAddress,' + 'Subnet Mask,' + 'Default Gateway,' + 'DHCP,' + 'DNS Servers'
$NICDestination = 'DC-NetworkConfig.csv'
Add-Content -Path $NICDestination $Rows
$Domains = (Get-ADForest).Domains
Foreach ($Domain in $Domains) {
$Rows = "Domain - $Domain"
Add-Content -Path $NICDestination $Rows
$DomainControllers = Get-ADDomainController -Server $Domain -Filter *
# Foreach ($Computer in $ComputerNames) {
Foreach ($DomainController in $DomainControllers) {
$Computer = $DomainController.HostName
$Server = $DomainController.Name
$Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computer -EA Stop |
Where-Object { $_.IPEnabled }
Foreach ($Network in $Networks) {
$IPAddress = $Network.IpAddress[0]
$SubnetMask = $Network.IPSubnet[0]
$DefaultGateway = $Network.DefaultIPGateway
$DNSServers = $Network.DNSServerSearchOrder
$IsDHCPEnabled = $false
If ($Network.DHCPEnabled) {
$IsDHCPEnabled = $true
}
$MACAddress = $Network.MACAddress
$OutputObj = New-Object -Type PSObject
$OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Server.ToUpper()
$OutputObj | Add-Member -MemberType NoteProperty -Name IPAddress -Value $IPAddress
$OutputObj | Add-Member -MemberType NoteProperty -Name SubnetMask -Value $SubnetMask
$OutputObj | Add-Member -MemberType NoteProperty -Name Gateway -Value ($DefaultGateway -join ',')
$OutputObj | Add-Member -MemberType NoteProperty -Name IsDHCPEnabled -Value $IsDHCPEnabled
$OutputObj | Add-Member -MemberType NoteProperty -Name DNSServers -Value ($DNSServers -join ',')
$OutputObj | Format-Table -AutoSize
$Row = "$Server," + "$IPAddress," + "$SubnetMask," + "$DefaultGateway," + "$ISDHCPEnabled," + "$DNSServers"
Add-Content -Path $NICDestination $Row
}
}
}
Sample output (notice all DCs have point to a core DC and themselves for DNS)
This configuration may be as desired, or it could be a bad configuration depending on the environment and / or the goals of IT.
To prevent corruption in Active Directory, a feature introduced in Windows 2003, is still a needed and worthy setting to keep enabled. When there are replication issues, and possibly lingering old objects in AD, it is good to verify what DCs have this configured and which ones do not. As a best practice, this should be enabled. Please refer to this article for reference.
Using the below code, we can check the 'strict replication consistency' setting for all DCs in a domain:
$DCs = (Get-ADDomainController -Filter *).Name | Sort-Object
Foreach ($DC in $DCs) {
$Script = {
$Name = 'Strict Replication Consistency'
$RegistryPath = 'HKLM:\System\CurrentControlSet\Services\NTDS\Parameters\'
$Val = (Get-ItemProperty -Path $RegistryPath -Name $Name).$Name
Return $Val
}
$StrictCheck = Invoke-Command -ComputerName $DC -ScriptBlock $Script
If ($StrictCheck -eq '1') {
Write-Host " * Strict Replication Consistency is enabled on the $DC Domain Controller." -ForegroundColor Cyan
}
Else {
Write-Host " * Strict Replication Consistency is disabled on the $DC Domain Controller." -ForegroundColor Yellow
}
}
Real results from this PowerShell code block
If you need to check multiple forests / domains, some code adjustment would be necessary.
Lastly, Windows servers include a built-in Best Practices Analyzer for each role that is installed on a server, below are two examples:
Active Directory and DNS BPA GUI
These are also accessible with PowerShell with Invoke-BPAModule and Get-BPAResult. BPAs work off a system of 'models' which correspond to the Windows Role that is installed on a server. For example, the DNS role has a DNSServer model name and AD-Domain-Services' model is DirectoryServices. We can get these Model names from the Get-BPAModel cmdlet to help spell these out. In the below code, we query two roles (DNS and DC) and if they are installed the Model name for each is added to a variable to be processed by the two previously mentioned cmdlets. Now, the output of this effort results in a CSV file for each BPA Model that was run.
Sample Code:
# Variables
$FilePath = (Get-Item -Path ".\" -Verbose).FullName
$Server = $Env:ComputerName
$BPA = @()
If ((Get-WindowsFeature AD-Domain-Services).Installed) {$BPA += "Microsoft/Windows/DirectoryServices"}
If ((Get-WindowsFeature DNS).Installed) {$BPA += "Microsoft/Windows/DNSServer"}
Foreach ($Model in $bpa) {
$Name = $Model.Replace("Microsoft/Windows/","")
$CSV = "BPA-Results-$Name-$Server.csv"
Invoke-BPAModel $Model -ErrorAction SilentlyContinue
Get-BPAResult -BestPracticesModelId $Model -ErrorAction SilentlyContinue |
Where-Object {$_.Problem -ne $Null} |
Select-Object ResultNumber,Severity,Category,Title,Problem,Impact,Resolution |
Export-Csv $CSV -NoTypeInformation -Encoding UTF8
}
While this article does not provide PowerShell for every scenario it does cover quite the basics of how PowerShell can be used, even in conjunction with non-PowerShell tools, in troubleshooting scenarios. Active Directory by its very nature can be very complex and because of this complexity a variety of tools are often used to troubleshoot problems. Sometimes clues are provided by application issues, user frustration or monitoring software notifications. In the end it is up to the administrator to choose the best tool for the job and to sometimes scrap a particular troubleshooting direction, backtrack and start all over with fresh tools, scripts, etc. to resolve an issue. PowerShell can provide a lot of information as well as rely on legacy tools for these scenarios. Happy hunting!
Managing Active Directory is one of the most time-consuming recurring tasks of many IT administrators and system engineers.
Creating and maintaining users and groups, managing OUs and computer accounts, providing detailed AD reports is constantly on the to-do lists.
Let us show you how you can streamline, automate, delegate and monitor all your Active Directory processes and tasks.
Save time, reduce errors, and focus on critical IT projects.
We announce all upcoming webinars in our newsletter, so you don't miss a webinar that's of interest to you.
Sep 30, 2024 by Frank Kresse
We have just released our latest ScriptRunner update, version 7.1, packed with powerful new features aimed at making IT...
Aug 16, 2024 by Heiko Brenn
Welcome to Scriptember! We are thrilled to announce the launch of a unique, month-long campaign dedicated to...
Aug 14, 2024 by Jeffery Hicks
I'd like to think that because you are reading this, you are a professional PowerShell user and this article will be a...
Damian Scoles is a ten-time Microsoft MVP specializing in Exchange, Office 365 and PowerShell who has 25 years of IT industry experience. He is based in the Chicago area and started out managing Exchange 5.5 and Windows NT. Over the years he has worked with Office 365 since BPOS and his experience has grown to include Azure AD, Security and Compliance Admin Centers, and Exchange Online. His community outreach includes contributing to TechNet forums, creating PowerShell scripts that can be found on his blogs, writing in-depth PowerShell / Office365 / Exchange blog articles, tweeting, and creating PowerShell videos on YouTube. He has written five PowerShell books and is also actively working on the book "Microsoft 365 Security for IT Pros".