Improve company productivity with a Business Account.Sign Up

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 65
  • Last Modified:

Clean stale records in AD and DNS

Hello Team,

Can someone please provide me with a nice script or free utility to identify all stale records in DNS and Active directory environment?

need that information exported to a CSV file, and full compatible with Windows 2012 R2 servers and PowerShell
Jerry Seinfield
Jerry Seinfield
3 Solutions
sAMAccountNameSr. Systems EngineerCommented:
There isnt really a way to determine if a record is stale other than looking for a host behind the record.  Are you talking about dynamic records or static?  

We should start with what your issue is and what are you trying to solve for...
Vaseem MohammedCommented:
I would point you to Aging and Scavenging feature
Refer to : Use Aging and Scavenging
sAMAccountNameSr. Systems EngineerCommented:
Aging and scavenging wont do anything for static records, which is why I asked.  I think before anyone provides a solution, we all need to understand the requirement.
Making Bulk Changes to Active Directory

Watch this video to see how easy it is to make mass changes to Active Directory from an external text file without using complicated scripts.

Jerry SeinfieldAuthor Commented:
How can Identify and then delete static and dynamic stale records? if that even possible?
David Johnson, CD, MVPOwnerCommented:
2 powershell scripts one for AD and one for DNS
# Get the Current Date  
# Number of Days to check back.    
# Organizational Unit to search  
Import-Module ActiveDirectory 
GET-ADUSER -filter * -SearchBase $OU -properties LastLogonDate | where { $_.LastLogonDate.AddDays($NumberDays) -lt $CurrentDate } | Format-Table 
# Add in a | DISABLE-ADAccount to AUTOMATICALLY Disable those accounts.  
# Line should read like this if you want to do that  
# GET-ADUSER -filter * -SearchBase $OU -properties LastLogonDate | where { $_.LastLogonDate.AddDays($NumberDays) -lt $CurrentDate } | Disable-ADAccount 

Open in new window

#Requires -Module ActiveDirectory,DnsServer 
    This script will report on all dynamic DNS records in a particular DNS zone that 
    are at risk of being scavenged by the DNS scavenging process. 
    Created on:     8/22/2014 
    Created by:     Adam Bertram 
    Filename:       Get-RecordsToBeScavenged.ps1 
    Requirements:   An AD-integrated DNS zone 
    PS> Get-RecordsToBeScavenged.ps1 -DnsZone myzone -WarningDays 5 
    This example will find all DNS records in the zone 'myzone' that are set to be scavenged 
    within 5 days. 
    The DNS server that will be queried 
    The DNS zone that will be used to find records 
.PARAMETER WarningDays 
    The number of days ahead of scavenge time you'd like to report on.  By default, this script 
    only displays DNS records set to be scavenged within 1 day. 
param ( 
    [string]$DnsServer = (Get-ADDomain).ReplicaDirectoryServers[0], 
    [int]$WarningDays = 1 
begin { 
    function Get-DnsHostname ($IPAddress) { 
        ## Use nslookup because it's much faster than any other cmdlet 
        $Result = nslookup $IPAddress 2> $null 
        $Result| where { $_ -match 'name' } | foreach { 
            $_.Replace('Name:    ', '') 
    Function Test-Ping ($ComputerName) { 
        try { 
            $oPing = new-object; 
            if (($oPing.Send($ComputerName, 200).Status -eq 'TimedOut')) { 
            } else { 
        } catch [System.Exception] { 
process { 
    try { 
        ## Check if scavenging and aging is even enabled on the server and zone 
        $ServerScavenging = Get-DnsServerScavenging -Computername $DnsServer 
        $ZoneAging = Get-DnsServerZoneAging -Name $DnsZone -ComputerName $DnsServer 
        if (!$ServerScavenging.ScavengingState) { 
            Write-Warning "Scavenging not enabled on server '$DnsServer'" 
            $NextScavengeTime = 'N/A' 
        } else { 
            $NextScavengeTime = $ServerScavenging.LastScavengeTime + $ServerScavenging.ScavengingInterval 
        if (!$ZoneAging.AgingEnabled) { 
            Write-Warning "Aging not enabled on zone '$DnsZone'" 
        ## A record won't be scavengable until the refresh + no-refresh period has elapsed.  Set a threshold 
        ## of this time plus a buffer to give the user a heads up ahead of time. 
        $StaleThreshold = ($ZoneAging.NoRefreshInterval.Days + $ZoneAging.RefreshInterval.Days) + $WarningDays 
        ## Find all dynamic DNS host records in the zone that haven't updated their timestamp in a long time 
        ## ensuring to only include the hosts ending with the zone name.  If not, by default, Get-DnsServerResourceRecord 
        ## will include a record with and without the zone name appended 
        $StaleRecords = Get-DnsServerResourceRecord -ComputerName $DnsServer -ZoneName $DnsZone -RRType A | where { $_.TimeStamp -and ($_.Timestamp -le (Get-Date).AddDays("-$StaleThreshold")) -and ($_.Hostname -like "*.$DnsZone") } 
        foreach ($StaleRecord in $StaleREcords) { 
            ## Get the IP address of the host to preform a reverse DNS lookup later 
            $RecordIp = $StaleRecord.RecordData.IPV4Address.IPAddressToString 
            ## Perform a reverse DNS lookup to find the actual hostname for that IP address. 
            ## Sometimes when a record has been out of commission for a long time duplicate 
            ## records can be created and the actual hostname for the IP address doesn't match 
            ## the old DNS record hostname anymore. 
            $ActualHostname = Get-DnsHostname $RecordIp 
            if ($ActualHostname) { 
                ## There's a PTR record for the host record.  Ping the hostname to see if it's 
                ## still online.  This is to only pay attention to the computers that may still 
                ## be online but have a problem updating their record. 
                $HostOnline = Test-Ping -Computername $ActualHostname 
            } else { 
                $HostOnline = 'N/A'  
                'Server' = $DnsServer 
                'Zone' = $DnsZone 
                'RecordHostname' = $StaleRecord.Hostname 
                'RecordTimestamp' = $StaleRecord.Timestamp 
                'IsScavengable' = (@{ $true = $false; $false = $true }[$NextScavengeTime -eq 'N/A']) 
                'ToBeScavengedOn' = $NextScavengeTime 
                'ValidHostname' = $ActualHostname 
                'RecordMatchesValidHostname' = $ActualHostname -eq $StaleRecord.Hostname 
                'HostOnline' = (@{ $true = $HostOnline; $false = 'N/A' }[$ActualHostname -eq $StaleRecord.Hostname]) 
    } catch { 
        Write-Error $_.Exception.Message 

Open in new window
David Johnson, CD, MVPOwnerCommented:
asked and answered
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Making Bulk Changes to Active Directory

Watch this video to see how easy it is to make mass changes to Active Directory from an external text file without using complicated scripts.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now