Creating and Updating DNS Records in Microsoft DNS Servers with C# .NET and WMI.

“No, just a wild stab in the dark – which, incidentally, is what you’ll be getting if you don’t start being a bit more helpful!” – Blackadder.

I do enjoy some of the random and unhelpful error messages that can come out of WMI, for example “generic error”. So helpful. Trying to resolve generic errors is much like trying to find a piece of hay in a massive stack full of needles – there is a process, but chances are you’re not going to enjoy it.

The example below can be used to create a new DNS A record in a Microsoft DNS Server, or update an existing A record. It’s a fairly standard example of how to use WMI, but with a couple of issues to look out for. Let’s start with the code.

private void UpdateARecord(string strDNSZone, string strHostName, string strIPAddress)
{
	ManagementScope mgmtScope = new ManagementScope(@"\\.\Root\MicrosoftDNS");
	ManagementClass mgmtClass = null;
	ManagementBaseObject mgmtParams = null;
	ManagementObjectSearcher mgmtSearch = null;
	ManagementObjectCollection mgmtDNSRecords = null;
	string strQuery;

	strQuery = string.Format("SELECT * FROM MicrosoftDNS_AType WHERE OwnerName = '{0}.{1}'", strHostName, strDNSZone);

	mgmtScope.Connect();

	mgmtSearch = new ManagementObjectSearcher(mgmtScope, new ObjectQuery(strQuery));

	mgmtDNSRecords = mgmtSearch.Get();

	// Multiple A records with the same record name, but different IPv4 addresses, skip.
	if (mgmtDNSRecords.Count > 1)
	{
		// Take appropriate action here.
	}
	// Existing A record found, update record.
	else if (mgmtDNSRecords.Count == 1)
	{
		foreach (ManagementObject mgmtDNSRecord in mgmtDNSRecords)
		{
			if (mgmtDNSRecord["RecordData"].ToString() != strIPAddress)
			{
				mgmtParams = mgmtDNSRecord.GetMethodParameters("Modify");
				mgmtParams["IPAddress"] = strIPAddress;

				mgmtDNSRecord.InvokeMethod("Modify", mgmtParams, null);
			}

			break;
		}
	}
	// A record does not exist, create new record.
	else
	{
		mgmtClass = new ManagementClass(mgmtScope, new ManagementPath("MicrosoftDNS_AType"), null);

		mgmtParams = mgmtClass.GetMethodParameters("CreateInstanceFromPropertyData");
		mgmtParams["DnsServerName"] = Environment.MachineName;
		mgmtParams["ContainerName"] = strDNSZone;
		mgmtParams["OwnerName"] = string.Format("{0}.{1}", strHostName.ToLower(), strDNSZone);
		mgmtParams["IPAddress"] = strIPAddress;

		mgmtClass.InvokeMethod("CreateInstanceFromPropertyData", mgmtParams, null);				
	}
}

From a WMI perspective, there’s nothing out of the ordinary happening in the code. First we start with a WMI WQL query to look for existing DNS records that match the host name and domain of the record we wish to create/update. When I used to do this in VBScript many years ago, my query also included ‘AND DomainName = ‘domainnamehere.com’. Interestingly enough, that worked with VBScript, but in C# it gave me generic WMI errors if the record I was searching for did not exist. Granted, a try/catch around it helped, but the query should not have failed – it should have simply returned a collection with 0 items. By removing the DomainName portion of the query, the query now behaves correctly.

So, to logic. The application logic here looks for an existing A record for the specified host and domain name. If multiple records match that query (e.g. round robin A records), then this code makes no attempt to change the record. If you wanted to update one of the round robin A records, you’d ideally need to search for that record specifically by also specifying its current value. For example, you might have a DNS record for host1 with an IP address of 10.1.1.1, and a second record with the same name, but an IP address of 10.1.1.2. You could simply modify the code to find the record with the IP address of 10.1.1.1 and update that.

If there is only one record with that name, then check if the IP address of the existing record matches the new IP address – if so, skip it (no change required). If the IP address doesn’t match, then update the record.

Finally, if the record could not be found, create a new record with the appropriate details.

As always, the try/catch structured exception handling is missing from the example – with that additional code, this example would have been several pages long.

There you have it. This example is easily modifiable to change other types of DNS records, create zones, make other changes etc. Simply look for the DNS WMI Provider help from Microsoft and you can see the WMI classes detailed there.

~ Mike

3 thoughts on “Creating and Updating DNS Records in Microsoft DNS Servers with C# .NET and WMI.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s