user1276012 user1276012 - 3 months ago 19
PowerShell Question

How to validate deleting a DNS entry with powershell

I have a (at least what I think) tricky problem with a Server 2008 R2 domain. I wrote a cleanup script for AD computer accounts. Beside the account in AD I want to delete SCCM and DNS accounts. But with DNS I have a problem. I need to log everything as my script will run timed as a job each day.
With the normal AD module cmdlets all work great by using something like this:

Remove-ADComputer -Identity $account -confirm:$false

if($?){
Write-Log -LogContent "Delete-OldADaccount: successfully deleted account `"$($account.name)`" with LastLogondate `"$($account.LastLogondate)`", full path `"$($account.distinguishedname)`"" -LogPath $logFile
} else {
Write-Log -LogContent "Delete-OldADaccount: failed to delete account `"$($account.name)`": $($error[0].Exception.Message)" -LogPath $logFile -Level 'Warn'
}


For deleting old DNS entries I found two solutions for Server 2008 R2 (I can't use those cool new Server 2012 DNS modules for ps):

dnscmd $DNSServer /RecordDelete $ZoneName $Computer A /f


and

Get-WmiObject -ComputerName $dnsserver -Namespace 'Root\MicrosoftDNS' -class MicrosoftDNS_AType -Filter "domainname = '$computer'" | Remove-WmiObject


But both commands (dnscmd and Remove-WmiObject) always return true, even if there were no records in DNS matching my computer account's name. So I cant use a similar construct as above.

So I tried something like this:

try{
[System.Net.DNS]::GetHostEntry($computer)
Get-WmiObject -ComputerName $dns -Namespace 'Root\MicrosoftDNS' -class MicrosoftDNS_AType -Filter "domainname = '$computer'" | Remove-WmiObject -whatif
Get-WmiObject -ComputerName $dns -Namespace 'Root\MicrosoftDNS' -class MicrosoftDNS_AAAAType -Filter "domainname = '$computer'" | Remove-WmiObject -whatif
Write-Log -LogContent "Delete-OldADaccount: successfully deleted DNS entry for `"$($computer)`"" -LogPath $logFile
}
catch {
Write-Log -LogContent "Delete-OldADaccount: failed to delete DNS entry for `"$($computer)`": $($error[0].Exception.Message)" -LogPath $logFile -Level 'Warn'
}


With the static function
[System.Net.DNS]::GetHostEntry($computer)
I test if there is at least an ipv4 entry (as ipv6 is deactivated on my system I would get an exception if there is only an ipv6 entry. If both ipv4 and ipv6 exist it works). If there is an entry it proceeds with the Remove-WmiObject cmdlet for ipv4 and ipv6.
If there is no such entry in DNS I get an exception and directly jump into the catch-block where I log the error.
But even with this method I have no clue later if the Remove-WmiObject was successful. I would have to do a
ipconfig /flushdns
and re-run the command
[System.Net.DNS]::GetHostEntry($computer)
to see if it now fails and interpret this as "entries deleted".

Please, is there another cmdlet or way for Server 2008 R2 to delete an entry from DNS and validate if the deletion was successful? Help ;)

Answer

I can't use those cool new Server 2012 DNS modules for ps

Yes you can, as long as you have at least one machine new enough to run them. They work just fine against a 2008 R2 domain controller. This would simplify things a lot!

Otherwise, you can still use CIM/WMI calls to retrieve the value of the record like you're already doing instead of using GetHostEntry.

Example, courtesy of Jon Dechiro

if (Get-WmiObject -ComputerName $dnsserver -Namespace 'Root\MicrosoftDNS' -class MicrosoftDNS_AType -Filter "domainname = '$computer'") { 
    Write-Log -LogContent "Delete-OldADaccount: failed to delete DNS entry for "$($computer)": Entry still exists on $dnsserver" -LogPath $logFile -Level 'Warn' 
} else { 
    Write-Log -LogContent "Delete-OldADaccount: successfully deleted DNS entry for "$($computer)"" -LogPath $logFile 
}