Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to troubleshoot client DNS.
Microsoft Scripting Guy, Ed Wilson, is here. It seems that when I travel invariably at some point on the trip I end up in a hotel that has DNS issues.
In the past, that meant opening up the CMD prompt and typing a bunch of cryptic commands. Not anymore. On my Windows 8 laptop (and even on my Windows Surface RT), I can use functions from the dnsclient module to do my troubleshooting.
Of course, with Windows PowerShell 3.0 (which comes on Windows 8, Windows Surface, and Windows Server 2012) knowing what module contains what function (or cmdlet) is not required.
Viewing the DNS client settings
If I am experiencing connectivity issues, and I suspect a DNS issue, one of the first things I do is check to see what DNS server my device uses. To find this information, I use the Get-DNSClient function. This command is shown here.
19:09 C:\> Get-DnsClient
InterfaceAlias Interface ConnectionSpecificSuffix ConnectionSpecificSuffixSearchList
-------------- --------- ------------------------ --------------------
Local Area Connection* 14 33 {}
vEthernet (WirelessSwitch) 31 owv.atl.wayport.net {}
isatap.owv.atl.wayport.net 44 owv.atl.wayport.net {}
Local Area Connection* 12 25 {}
vEthernet (InternalSwitch) 19 {}
isatap.{FC2087E9-6988-45E... 40 {}
Loopback Pseudo-Interface 1 1 {}
Teredo Tunneling Pseudo-I... 34 {}
6TO4 Adapter 39 {}
The preceding output is a bit much. In fact, it is too much to read. One easy way to filter the output is to display only the connections that have a connection suffix. This command is shown here.
19:09 C:\> Get-DnsClient | ? connectionspecificsuffix
InterfaceAlias Interface ConnectionSpecificSuffix ConnectionSpecificSuffixSearchList
-------------- --------- ------------------------ --------------------
vEthernet (WirelessSwitch) 31 owv.atl.wayport.net {}
isatap.owv.atl.wayport.net 44 owv.atl.wayport.net {}
If I want to see the network adapters associated with the particular network interface, I pipe the results to the Get-NetAdapter function. This command is shown here.
Note Interface 44 does not exist on my laptop and an error appears. To avoid the errors, specify an erroraction of 0.
19:10 C:\> Get-DnsClient | ? connectionspecificsuffix | Get-NetAdapter
Get-NetAdapter : No MSFT_NetAdapter objects found with property 'InterfaceIndex'
equal to '44'. Verify the value of the property and retry.
At line:1 char:46
+ Get-DnsClient | ? connectionspecificsuffix | Get-NetAdapter
+ ~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (44:UInt32) [Get-NetAdapter], CimJobE
xception
+ FullyQualifiedErrorId : CmdletizationQuery_NotFound_InterfaceIndex,Get-NetAda
pter
Name InterfaceDescription ifIndex Status
---- -------------------- ------- ------
vEthernet (WirelessSwi... Hyper-V Virtual Ethernet Adapter #4 31 Up
Use PowerShell to check the DNS cache
Once I see that I have a valid DNS server assigned, I decide to view my DNS cache. I use the Get-DNSCache function as shown here.
Note Using the Get-DnsClientCache does not require Admin permissions.
19:12 C:\> Get-DnsClientCache
Entry RecordNameType Record Status Section TimeToLive
----- ---------- ------ ------ ------- ------
sxp.microsoft.com sxp.microsoft.com CNAME Success Answer 4
ajax.aspnetcdn.com ajax.aspnetcdn.com CNAME Success Answer 293
www.facebook.com www.facebook.com CNAME Success Answer 53
There are a couple of things important here. One is the TTL—that is the time-to-live of the record and it lets me know that the spx.microsoft.com record will be present in my DNS cache for 4 seconds. The www.facebook.com record will live for 53 seconds.
A CNAME record is a canonical name record, or an alias for a DNS domain. Knowing this information is useful because it lets me know that the domain name I see is not the “actual name” of the server. If using the CNAME to connect to the server does not work, I know where to go to see if the server is even up.
Here is an example of a CNAME record. I found this by piping a specific entry from the Get-DNSCLientCache to the Format-List cmdlet and, thereby, permitting me to view all of the information. The actual server name exists in the dataproperty. I use the following code to obtain the complete information.
12:35 C:\> (Get-DnsClientCache)[0] | fl *
TTL : 169
Caption :
Description :
ElementName :
InstanceID :
Data : prod.us.moneycentral.money.glbdns.microsoft.com
DataLength : 8
Entry : moneycentral.msn.com
Name : moneycentral.msn.com
Section : 1
Status : 0
TimeToLive : 169
Type : 5
PSComputerName :
CimClass : ROOT/StandardCimv2:MSFT_DNSClientCache
CimInstanceProperties : {Caption, Description, ElementName, InstanceID...}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
Finding missing records
The cool thing about using the Get-DnsClientCache Windows PowerShell cmdlet is that it is PowerShell, and as such, it returns objects. This means an easily parsable output. In the output below, several records are not available—this can obviously cause problems.
12:51 C:\> Get-DnsClientCache
Entry RecordNameType Record Status Section TimeToLive
----- ---------- ------ ------ ------- ------
ots.optimize.webtrends... ots.optimize.webtrends... CNAME Success Answer 100
_ldap._tcp.charlottesi... SRV NoRecords
_ldap._tcp.dc._msdcs.i... SRV NoRecords
<output truncated>
But in a long listing of the DNS client cache, identifying all of the missing records is a bit of a challenge. Therefore, it makes sense to filter the output via the Where-Object. This technique is shown here.
12:55 C:\> Get-DnsClientCache | ? status -eq 'NoRecords'
12:55 C:\>
The problem, unfortunately, is that no records return. The reason is because this is one of those occasions where the actual returned data does not match with the display data—in other words, I am attempting to filter on something that does not exist. To get to the bottom of the problem, I need to see the raw data. I can do that by piping the output to the Format-List cmdlet and viewing all of the properties. This technique is shown here.
12:55 C:\> Get-DnsClientCache | Format-List -Property * -Force
TTL : 0
Caption :
Description :
ElementName :
InstanceID :
Data :
DataLength : 0
Entry : _ldap._tcp.charlottesite._sites.dc._msdcs.iammred.net
Name :
Section : 0
Status : 9501
TimeToLive : 0
Type : 33
PSComputerName :
CimClass : ROOT/StandardCimv2:MSFT_DNSClientCache
CimInstanceProperties : {Caption, Description, ElementName, InstanceID...}
CimSystemProperties : Microsoft.Management.Infrastructure.CimSystemProperties
I examine the output and see that the status is 9501and not NoRecords. Once I change my Where-Object filter, I obtain exactly the output I expected. Here is the modified command and its associated output.
12:58 C:\> Get-DnsClientCache | ? status -eq 9501
Entry RecordNameType Record Status Section TimeToLive
----- ---------- ------ ------ ------- ------
_ldap._tcp.charlottesi... SRV NoRecords
_ldap._tcp.dc._msdcs.i... SRV NoRecords
_ldap._tcp.5765f6d1-cb... SRV NoRecords
12:58 C:\>
Join me tomorrow when I will talk some more about using Windows PowerShell to troubleshoot DNS issues on the client side.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy