Getting the Text Representation of a Microsoft DNS record using PowerShell Get-DnsServerResourceRecord cmdlet

Within Microsoft DNS server you'll see your zones and resource records.

Under the data column you'll see a nice simply text representation of each resource record.


This was also available back in the old days with the MicrosoftDNS_ResourceRecord WMI class.
https://docs.microsoft.com/en-us/windows/win32/dns/microsoftdns-resourcerecord


When using the new PowerShell cmdlet you'll find that each DNS record has its own strongly typed class which properties appropriate for each each resource type.



Nice. But you just want the full text representation. So you call ToString()... Problem.



The ToString() method just returns the type name. This is from CimInstance. Which is strange because when you look at the resource records as a collection they display a cut down version of the resource record text representation, this is the same output piping each resource record to Format-Table.



Even more interesting, piping a resource record to Format-List you get the full information as a textual representation. So how does this class (which is just a CimInstance) know how to cleverly display itself like this....?



The answer is the DnsServerPsProvider.Format.ps1xml file which you can find by searching the Windows directory on a Windows Server 2012 or newer machine with DNS installed. As you can see this xml file tells PowerShell to look for this class when formatting and ...




This script block is executed to format the text.


The problem is that this is implemented for the DnsServerResourceRecord class (not the resource data) so you can only format the whole resource record. You'd have to get this as text and hack out the resource record text from the overall string, not great.


To resolve this limitation you can take the scriptblock provided by Microsoft and convert it to a function as I've done here.

This is still a bit of a pain as the script won't be updated by new versions of the operating system, but I can't see another way of accessing this functionality directly, do drop me a message if you know a better way.




# Converts the specified well known account name to a security identifier.

Function Get-DnsServerResourceRecordTextRepresentation

{


    [CmdletBinding()]

    param(

        [Parameter(ValueFromPipeline)]

        [Microsoft.Management.Infrastructure.CimInstance] $ResourceRecord

    )


    if($ResourceRecord.RecordType -eq "A") { return [System.Convert]::ToString($ResourceRecord.RecordData.IPv4Address); }

    if($ResourceRecord.RecordType -eq "AAAA") { return [System.Convert]::ToString($ResourceRecord.RecordData.IPv6Address); }

    if($ResourceRecord.RecordType -eq "AFSDB") { return "[" + $ResourceRecord.RecordData.SubType + "][" + $ResourceRecord.RecordData.ServerName + "]"; }

    if($ResourceRecord.RecordType -eq "ATMA") { return "[" + $ResourceRecord.RecordData.AddressType + "][" + $ResourceRecord.RecordData.Address + "]"; }

    if($ResourceRecord.RecordType -eq "CNAME") { return $ResourceRecord.RecordData.HostNameAlias; }

    if($ResourceRecord.RecordType -eq "DHCID") { return $ResourceRecord.RecordData.DHCID; }

    if($ResourceRecord.RecordType -eq "DNAME") { return $ResourceRecord.RecordData.DomainNameAlias; }

    if($ResourceRecord.RecordType -eq "HINFO") { return "[" + $ResourceRecord.RecordData.Cpu + "][" + $ResourceRecord.RecordData.OperatingSystem + "]"; }

    if($ResourceRecord.RecordType -eq "ISDN") { return "[" + $ResourceRecord.RecordData.IsdnNumber + "][" + $ResourceRecord.RecordData.IsdnSubAddress + "]"; }

    if($ResourceRecord.RecordType -eq "MX") { return "[" + $ResourceRecord.RecordData.Preference + "][" + $ResourceRecord.RecordData.MailExchange + "]"; }

    if($ResourceRecord.RecordType -eq "NS") { return $ResourceRecord.RecordData.NameServer; }

    if($ResourceRecord.RecordType -eq "PTR") { return $ResourceRecord.RecordData.PtrDomainName; }

    if($ResourceRecord.RecordType -eq "RP") { return "[" + $ResourceRecord.RecordData.ResponsiblePerson + "][" + $ResourceRecord.RecordData.Description + "]"; }

    if($ResourceRecord.RecordType -eq "RT") { return "[" + $ResourceRecord.RecordData.Preference + "][" + $ResourceRecord.RecordData.IntermediateHost + "]"; }

    if($ResourceRecord.RecordType -eq "SOA") { return "[" + $ResourceRecord.RecordData.SerialNumber + "][" + $ResourceRecord.RecordData.PrimaryServer + "][" + $ResourceRecord.RecordData.ResponsiblePerson + "][" + $ResourceRecord.RecordData.ExpireLimit + "][" + $ResourceRecord.RecordData.MinimumTimetoLive + "][" + $ResourceRecord.RecordData.RefreshInterval + "][" + $ResourceRecord.RecordData.RetryDelay + "]"; }

    if($ResourceRecord.RecordType -eq "SRV") { return "[" + $ResourceRecord.RecordData.Priority + "][" + $ResourceRecord.RecordData.Weight + "][" + $ResourceRecord.RecordData.Port + "][" + $ResourceRecord.RecordData.DomainName + "]"; }

    if($ResourceRecord.RecordType -eq "TXT") { return $ResourceRecord.RecordData.DescriptiveText; }

    if($ResourceRecord.RecordType -eq "WINS") { return "[" + $ResourceRecord.RecordData.Replicate + "][" + $ResourceRecord.RecordData.LookupTimeout + "][" + $ResourceRecord.RecordData.CacheTimeout + "][" + $ResourceRecord.RecordData.WinsServers + "]"; }

    if($ResourceRecord.RecordType -eq "WINSR") { return "[" + $ResourceRecord.RecordData.Replicate + "][" + $ResourceRecord.RecordData.LookupTimeout + "][" + $ResourceRecord.RecordData.CacheTimeout + "][" + $ResourceRecord.RecordData.ResultDomain + "]"; }

    if($ResourceRecord.RecordType -eq "WKS") { return "[" + $ResourceRecord.RecordData.InternetProtocol + "][" + $ResourceRecord.RecordData.Service + "][" + $ResourceRecord.RecordData.InternetAddress + "]"; }

    if($ResourceRecord.RecordType -eq "X25") { return $ResourceRecord.RecordData.PSDNAddress; }

    if($ResourceRecord.RecordType -eq "DNSKEY" ) 

    { 

        if($ResourceRecord.RecordData.Revoked -eq $True) { $dnskeyData  = "[Revoked]"; }

        if($ResourceRecord.RecordData.SecureEntryPoint -eq $True) { $dnskeyData  += "[SEP]"; }

        if($ResourceRecord.RecordData.ZoneKey -eq $True) { $dnskeyData  += "[ZoneKey]"; }

        $dnskeyData += "[" + $ResourceRecord.RecordData.CryptoAlgorithm + "][" + $ResourceRecord.RecordData.KeyTag + "][" + $ResourceRecord.RecordData.KeyProtocol + "][" + $ResourceRecord.RecordData.Base64Data + "]"

        return $dnskeyData

    }

    if($ResourceRecord.RecordType -eq "DS") { return "[" + $ResourceRecord.RecordData.KeyTag + "][" + $ResourceRecord.RecordData.CryptoAlgorithm + "][" + $ResourceRecord.RecordData.DigestType + "][" + $ResourceRecord.RecordData.Digest + "]"; }

    if($ResourceRecord.RecordType -eq "NSEC" ) { return "[" + $ResourceRecord.RecordData.Name + "][" + $ResourceRecord.RecordData.CoveredRecordTypes + "]"; }

    if($ResourceRecord.RecordType -eq "NSEC3" ) { return "[" + $ResourceRecord.RecordData.HashAlgorithm + "][" + $ResourceRecord.RecordData.OptOut + "][" + $ResourceRecord.RecordData.Iterations + "][" + $ResourceRecord.RecordData.Salt + "][" + $ResourceRecord.RecordData.NextHashedOwnerName + "][" + $ResourceRecord.RecordData.CoveredRecordTypes + "]"; }

    if($ResourceRecord.RecordType -eq "NSEC3PARAM" ) { return "[" + $ResourceRecord.RecordData.HashAlgorithm + "][" + $ResourceRecord.RecordData.Iterations + "][" + $ResourceRecord.RecordData.Salt + "]"; }

    if($ResourceRecord.RecordType -eq "RRSIG" ) { return "[" + $ResourceRecord.RecordData.TypeCovered + "][" + $ResourceRecord.RecordData.CryptoAlgorithm + "][" + $ResourceRecord.RecordData.KeyTag + "]["+ $ResourceRecord.RecordData.LabelCount + "]["  + $ResourceRecord.RecordData.NameSigner + "][" + "SignatureInception: " + $ResourceRecord.RecordData.SignatureInception + "][" + "SignatureExpiration: " + $ResourceRecord.RecordData.SignatureExpiration + "][" + $ResourceRecord.RecordData.OriginalTtl + "][" + $ResourceRecord.RecordData.Signature + "]"; }

    if($ResourceRecord.RecordType -eq "UNKNOWN" ) { return $ResourceRecord.RecordData.Data; }

    if($ResourceRecord.RecordType -eq "TLSA" ) { return "[" + $ResourceRecord.RecordData.CertificateUsage + "][" + $ResourceRecord.RecordData.Selector + "][" + $ResourceRecord.RecordData.MatchingType + "][" + $ResourceRecord.RecordData.CertificateAssociationData + "]"; }


}




While you're here... why not check out our DNS audit and documentation tool? 




Comments

Popular posts from this blog

Windows Server 2016, 2019, 2022, Windows 10 and Windows 11: Date and time "Some settings are managed by your organization".

TFTPD32 or TFTPD64 reports Bind error 10013 An attempt was made to access a socket in a way forbidden by its access permissions.

Windows Server 2019 desktop icons such as My Computer, Windows cannot access the specified device, path, or file.