I l@ve RuBoard Previous Section Next Section

7.10 Examining the Microsoft Windows Registry for a List of Name Server Addresses

Credit: Wolfgang Strobl

7.10.1 Problem

You need to find out which DNS name servers are being used, but you're on Microsoft Windows, so you can't just parse the resolv.conf file, as you might do on Unix and Unix-like platforms.

7.10.2 Solution

On Windows, DNS servers (like much other information) can be found in the registry, which can be accessed with the standard module _winreg:

import string
import _winreg

def binipdisplay(s):
    "convert a binary array of ip addresses to a python list"
    if len(s)%4!= 0:
        raise EnvironmentError # well ...
    ol=[]
    for i in range(len(s)/4):
        s1=s[:4]
        s=s[4:]
        ip=[]
        for j in s1:
            ip.append(str(ord(j)))
        ol.append(string.join(ip,'.'))
    return ol

def stringdisplay(s):
    'convert "d.d.d.d,d.d.d.d" to ["d.d.d.d","d.d.d.d"]'
    return string.split(s,",")

def RegistryResolve(  ):
    """ Return the list of dotted-quads addresses of name servers found in
    the registry -- tested on NT4 Server SP6a, Win/2000 Pro SP2, XP, ME
    (each of which has a different registry layout for nameservers!) """

    nameservers=[]
    x=_winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
    try:
        y= _winreg.OpenKey(x,
         r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters")
    except EnvironmentError: # so it isn't NT/2000/XP
        # Windows ME, perhaps?
        try: # for Windows ME
            y = _winreg.OpenKey(x,
              r"SYSTEM\CurrentControlSet\Services\VxD\MSTCP")
            nameserver, dummytype = _winreg.QueryValueEx(y,'NameServer')
            if nameserver and not (nameserver in nameservers):
                nameservers.extend(stringdisplay(nameserver))
        except EnvironmentError:
            pass # Must be another Windows dialect, so who knows?
        return nameservers

    nameserver = _winreg.QueryValueEx(y,"NameServer")[0]
    if nameserver:
        nameservers = [nameserver]
    _winreg.CloseKey(y)
    try: # for win2000
        y = _winreg.OpenKey(x, r"SYSTEM\CurrentControlSet\Services\Tcpip"
                               r"\Parameters\DNSRegisteredAdapters")
        for i in range(1000):
            try:
                n = _winreg.EnumKey(y,i)
                z = _winreg.OpenKey(y,n)
                dnscount,dnscounttype = _winreg.QueryValueEx(z,
                    'DNSServerAddressCount')
                dnsvalues,dnsvaluestype = _winreg.QueryValueEx(z,
                    'DNSServerAddresses')
                nameservers.extend(binipdisplay(dnsvalues))
                _winreg.CloseKey(z)
            except EnvironmentError:
                break
        _winreg.CloseKey(y)
    except EnvironmentError:
        pass

    try: # for XP
        y = _winreg.OpenKey(x,
         r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces")
        for i in range(1000):
            try:
                n = _winreg.EnumKey(y,i)
                z = _winreg.OpenKey(y,n)
                try:
                    nameserver,dummytype = _winreg.QueryValueEx(z,'NameServer')
                    if nameserver and not (nameserver in nameservers):
                        nameservers.extend(stringdisplay(nameserver))
                except EnvironmentError:
                    pass
                _winreg.CloseKey(z)
            except EnvironmentError:
                break
        _winreg.CloseKey(y)
    except EnvironmentError:
        # Print "Key Interfaces not found, just do nothing"
        pass

    _winreg.CloseKey(x)
    return nameservers

if _ _name_ _=="_ _main_ _":
    print "Name servers:",RegistryResolve(  )

7.10.3 Discussion

RegistryResolve returns a list of IP addresses (dotted quads) by scanning the registry for interfaces with name server entries. This is useful when porting utilities that scan resolv.conf from Unix-based systems to Microsoft Windows. As shown, the code handles differences between NT, 2000, XP, and ME (I haven't tried it on Windows 95/98, but it should work), and is thus a good example of the many huge differences under the cover that the system administrator must handle for systems that may appear to end users to be reasonably close to each other.

Checking which name servers each given machine is using is quite useful when administering that machine, or a whole network. Basically, all user access to the network is mediated by DNS. Since no user wants to work with dotted quads, almost all URLs use hostnames and not IP addresses. From the user's viewpoint, if a DNS server is down, or if name service is misconfigured for a given machine, it's almost as bad as if there is no network access at all. This recipe makes it feasible for you to keep an eye on this crucial aspect of networking service, available from Python scripts, for client machines running Windows (client machines running Unix or Unix-like systems are easy to use from this point of view, since /etc/resolv.conf is a text file, and a pretty easy one to parse).

7.10.4 See Also

Documentation for the standard module _winreg in the Library Reference; Windows API documentation available from Microsoft (http://msdn.microsoft.com).

    I l@ve RuBoard Previous Section Next Section