AD Forest DCDiag and RepAdmin Report

Two earlier posts, EASY TO READ DCDIAG REPORT and EASY TO READ REPADMIN RESULTS, included scripts for displaying the high level results of DCDiag and RepAdmin. I had since combined the two and made some tweaks, but it never really seemed right.

I’ve finally gotten around to making it presentable and more functional. It now displays all of the DCDiag tests and their results in two separate tables rather than just a few of the tests that I’d selected. It also accurately displays the server name for each set of tests. The previous versions would only create reports for a single domain, but now, since I work in a multi domain forest these days, it will grab the DCs in all domains in the forest.

The RepAdmin results are now broken up by domain controller and sorted by context. This makes it a little easier to read and track issues.

# http://www.anilerduran.com/index.php/2013/how-to-parse-dcdiag-output-with-powershell/

############
# Functions 
############
Function Get-ForestDomainControllers
    {
    $Results=@()
    foreach ($domain in (Get-ADForest).domains )
        {
        $Results+=(Get-ADdomain $domain).ReplicaDirectoryServers
        }
    Return $Results
    }

Function Get-DCDiagReport($DC)
    {
    "Testing $DC"
    $DCDIAG = dcdiag /s:$DC /v #/test:Intersite /test:topology
    $DCDiagResults = New-Object System.Object
    $DCDiagResults | Add-Member -name Server -Value $DC -Type NoteProperty -Force
    
    Foreach ($Entry in $DCDIAG) 
        {
        Switch -Regex ($Entry) 
            {
            "Starting" {$Testname = ($Entry -replace ".*Starting test: ").Trim()}
            "passed|failed" {If ($Entry -match "passed") {$TestStatus = "Passed"} Else {$TestStatus = "failed"}}
            }
            
        If ($TestName -ne $null -and $TestStatus -ne $null) 
            {
            $DCDiagResults | Add-Member -Type NoteProperty -name $($TestName.Trim()) -Value $TestStatus -Force
            }
        }
    Return $DCDiagResults
    }

Function Get-ReplReport 
    {
    "Starting Repadmin Tests"

    $Repl = repadmin /showrepl * /csv
    $ReplResults = $Repl | ConvertFrom-Csv 

    $ReplReport = @()

    Foreach ($result in $ReplResults) 
        {
        $ReplReport += New-object PSObject -Property @{
            "DestSite" = $Result.'Destination DSA Site'
            "Dest" = $Result.'Destination DSA'
            "NamingContext" = $Result.'Naming Context'
            "SourceSite" = $Result.'Source DSA Site'
            "Source" = $Result.'Source DSA'
            "Transport" = $Result.'Transport Type'
            "NumberFailures" = $Result.'Number of Failures'
            "LastFailureTime" = $Result.'Last Failure Time'
            "LastSuccessTime" = $Result.'Last Success Time'
            "LastFailureStatus" = $Result.'Last Failure Status'
            }
        }
    Return $ReplReport
    }

##############
# Gather Data 
##############

Clear-Host
Import-Module activedirectory

"Collecting Forest Domain Controllers"
$DCs=Get-ForestDomainControllers

"Starting DCDiag Tests"
$DCDiagRpt=@()
foreach ($DC in $DCs | sort)
    {
    $DCDiagRpt+=Get-DCDiagReport $DC.ToUpper()
    }

#################
# Display Results
#################

"Starting Repadmin Tests"
$ReplRrt=Get-ReplReport

"DCDiag Test Results (Page 1 of 2)"
$DCDiagRpt | ft Server,Connectivity,Advertising,DFSREvent,SysVolCheck,KccEvent,NCSecDesc,Replications,RidManager,Services,Intersite,LocatorCheck -AutoSize
"DCDiag Test Results (Page 2 of 2)"
$DCDiagRpt | ft Server,FrsEvent,KnowsOfRoleHolders,MachineAccount,NetLogons,ObjectsReplicated,SystemLog,VerifyReferences,CheckSDRefDom,CrossRefValidation -AutoSize

"Replication Test Results"
$Servers = $ReplRrt | select -ExpandProperty Source -Unique 

foreach ($Server in ($Servers | Sort))
    {
    "$Server"
    $ReplRrt | ? {$_.Source -eq $Server} | select "NamingContext","Dest","SourceSite","DestSite","NumberFailures","LastFailureTime","LastFailureStatus","LastSuccessTime","Transport" | sort NamingContext,Dest | ft -AutoSize
    }

PowerShell to Remove Password Not Required Flag in AD

We had a couple thousand users in our test AD that had the Password Not Required flag set without a password. This was causing an error when Microsoft Identity Management tried to set the password for these user objects.

We used the following script to remove the flag and set a password.

$Users = Get-ADUser -searchscope subtree -ldapfilter "(&(objectCategory=User)(userAccountControl:1.2.840.113556.1.4.803:=32))" 
$newPassword = (Read-Host -Prompt "Provide New Password" -AsSecureString)

foreach ($user in $Users)
    {
    Set-ADAccountPassword -Identity $User.samaccountname -NewPassword $newPassword -Reset
    Set-ADAccountControl $User.samaccountname -PasswordNotRequired $false
    }

Generate Unique Logon Name with PowerShell

This script takes the first name, last name, and middle initial to create a logon name so that it’s unique. It creates an array of available names for that user and then selects the first one that will work.

Param(
    $firstName = "Joseph",
    $LastName = "Streeter",
    $MI = "A"
    )

BEGIN 
    {
    Import-Module ActiveDirectory
    }

PROCESS 
    {
    Function Check-UserName($UserName)
        {
        if (Get-ADUser -f {samaccountname -eq $UserName} -ea 0) 
            {
            Return $False
            }
            Else
            {
            Return $True
            }
        }

    $UserNames = @()
    $UserNames += $firstName.substring(0,1) + $LastName
    $UserNames += $firstName.substring(0,1) + $MI + $LastName
  
    $i=1
    do
    {
    $UserNames += $firstName.substring(0,1) + $LastName + $i
    
    $i++    
    }
    while ($i -lt 99)
    
    foreach ($UserName in $UserNames)
        {
        if (Check-UserName $UserName -eq "True")
            {
            $UserName
            Break
            }
        }
    }

END 
    {
    Clear-Variable UserNames
    }

Script Creating DNS Records

This script creates Host A records for a list of hosts.

$records = "mimsvc,10.39.0.78","mimsps,10.39.0.78","mimsync,10.36.1.53","mimsvcsql,10.36.1.52","mimspssql,10.36.1.52","mimsyncsql,10.36.1.52"
$DNSServer = "DC"
$Zone = "domain.tld"

foreach ($record in $records)
    {
    $Name = $record.split(",")[0]
    $Ip = $record.split(",")[1]
    
    Add-DnsServerResourceRecordA -ComputerName $DNSServer -ZoneName $Zone -Name $Name -IPv4Address $Ip -PassThru
    }

Set Aging on All DNS Zones

A quick script to set the aging on all zones. In this case it’s only doing reverse lookup zones.

$zones = Get-DnsServerZone -ComputerName dc | ? {($_.IsReverseLookupZone -eq $True) -and ($_.IsDsIntegrated -eq $True)}
    
foreach ($zone in $zones) 
    {
    Set-DnsServerZoneAging -ComputerName dc -Name $zone.zonename -RefreshInterval 4.00:00:00 -NoRefreshInterval 4.00:00:00
    }

Find GPOs that aren’t linked or Don’t Contain Policies

Creates a list of all Group Policy objects that are not linked or don’t have any policies configured.

Import-Module grouppolicy

Write-Host "`nUnlinked GPOs`n"
$allGPOs = Get-GPO -All | sort DisplayName
ForEach ($gpo in $allGPOs) {
    $xml = [xml](Get-GPOReport $gpo.Id xml)
    If (!$xml.GPO.LinksTo) {
        $gpo.DisplayName
        }
    }

Write-Host "`nGPOs with no settings`n"
$allGPOs = Get-GPO -All | sort DisplayName
ForEach ($gpo in $allGPOs) {
    $xml = [xml](Get-GPOReport $gpo.Id xml)
    If ($xml.GPO.LinksTo) {
        If (!$xml.GPO.Computer.ExtensionData -and !$xml.GPO.User.ExtensionData) {
            $gpo.DisplayName
            }
        }
    }

Forefront Identity Manager Links

Links for FIM and the technology around it for my emersion into the product:

Network Location Awareness Issues with WS 2008 R2 Domain Controllers

There is a known issue with Windows Server 2008 R2 that causes the Network Location Awareness (NLA) service to incorrectly identify the network that it is connected to. By failing to correctly identify the network the public local firewall profile is applied to the NIC and causes connectivity issues.

Continue reading “Network Location Awareness Issues with WS 2008 R2 Domain Controllers”