Ever try to create DNS records in Code? Ever succeed in a reliable way? Yea, well, me neither.
There are typically two ways in Windows to create new DNS entries in your Microsoft DNS Server:
- Use the MMC to manually add records to your zone
- Write WMI code to add records to your zone
Both of these methods have their drawbacks. Using the MMC is great, but it requires a GUI. This isn't exactly ideal for automation.
Using WMI works (or so it's rumored) but requires the WMI Provider to be installed, which it's not by default. Finding and
installing this provider isn't trivial, and even once it's found and running, still requires writing a fair bit of WMI code.
My experience is that talking someone through the process of creating A and SRV records is difficult. I've done this over the phone
a few times, and it's not been pleasant. Writing WMI code that manipulates DNS and runs on customer machines has proven to
be equally frustrating.
To work around this problem, I wrote a bunch of code that relies on the DNS Command Line utility dnscmd.exe.
The command line tool is found in the “Windows Support Tools” installation, and is NOT installed by default. This can be found in the \Support directory on your original Windows CD. Install suptools.msi and you'll have this setup.
There are versions that I've found for:
- Windows XP
- Windows XP x64
- Windows 2003 Server
- Windows 2003 Server x64
I wasn't able to fine one for Vista, so I'm not sure what the deal is there yet.
Once installed, you can run the DNS command line tool. To create an A record, and some SRV records, the basic syntax is:
- dnscmd fattire /RecordAdd winfessor.com martini.1 A 192.168.5.100
- dnscmd fattire /RecordAdd winfessor.com _xmpp-client._tcp.martini.1 SRV 10 0 5222 martini.1.winfessor.com
- dnscmd fattire /RecordAdd winfessor.com _xmpp-server._tcp.martini.1 SRV 10 0 5269 martini.1.winfessor.com
To delete those same records:
- dnscmd fattire /Recorddelete winfessor.com _xmpp-client._tcp.martini.1 SRV
- dnscmd fattire /Recorddelete winfessor.com _xmpp-server._tcp.martini.1 SRV
I've built a little application around this little command line tool, and tied it to some of the DNS code that's inside the SoapBox Framework.
You can find a binary of the application at: DNSTests.exe. The full
C# source code can be found at: DNS. This source code is written in
.Net 2.0, and should run just fine on any x86, x64, or IA64 machine.
Make sure you save the EXE to your local computer, and then run it locally. If you try to run it directly from the web site, you won't
have sufficient permissions, and you'll get an ugly error. One of these days, I'll try to get around to publishing this as a Click-Once
application and signing it with our authenticode cert.
There was some fun to be had writing this code. I dug the code out of the SoapBox Framework that figures out the list of available DNS servers. This
uses the Win32 call GetNetworkParams. This code was originally written
by JD Conley, one of the other engineers here.
//alocate unmanged memory
IntPtr ptr = Marshal.AllocHGlobal((int)buffersize);
if (Win32GetNetworkParams(ptr, ref buffersize) != 0)
{
int errno = Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(errno);
}
FIXED_INFO info = (FIXED_INFO)Marshal.PtrToStructure(ptr,
typeof(FIXED_INFO));
this._DomainName = info.DomainName.Trim();
this._HostName = info.HostName.Trim();
this._NodeType = info.NodeType;
this._ScopeId = info.ScopeId.Trim();
//read first dns server's IP_ADDR_STRING
IP_ADDR_STRING dns = info.DnsServerList;
this._DnsServerList.Add(dns.IpAddress.Trim());
while (dns.Next != IntPtr.Zero)
{
//get next dns server
dns = (IP_ADDR_STRING)Marshal.PtrToStructure(dns.Next,
typeof(IP_ADDR_STRING));
this._DnsServerList.Add(dns.IpAddress.Trim());
}
//free unamanged memory
Marshal.FreeHGlobal(ptr);
Using this code, I can populate a dropdown of available DNS Servers.
Because my typical use for this is to create DNS records for the machine on which the code is running,
lookup up all of the Local IP Addresses is needed. Fortunately doing that and binding it to
a combo box is really pretty easy:
IPAddressList.DataSource = Dns.GetHostAddresses(Dns.GetHostName());
With all said and done, using this tool to create DNS records makes diagnosing problems and setting up test
DNS records much easier. Even though it requires installation of the Windows Support Tools, and for the running
user to be (in essence) a Domain Admin, it's a huge improvement on requiring users to do this by hand.