I wanted to be able to switch fast between different network configurations on my Windows development PC without using any kind of 3rd party software. So I had a quick look on Stackoverflow and found the beautiful wmi package. Windows Management Instrumentation (WMI) is Microsoft’s implementation of Web-Based Enterprise Management (WBEM), an industry initiative to provide a Common Information Model (CIM) for pretty much any information about a computer system. And the wmi package is a Python wrapper for it on top of pywin32.

So in the script below I use this wmi package to switch between different network configurations (ip address, dhcp, subnetmask, gateway). The configurations are stored in a dictionary and can be modified on demand. I wanted to be able to use the script from the command line but keep the hassle low. So I decided to give click a try. Click is a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary. It’s the “Command Line Interface Creation Kit”. It’s highly configurable but comes with sensible defaults out of the box. A great thing about click is that you can define choices for your variables. The choices are displayed when you call python netset.py --help. I used this to allow only the names of my defined network configurations.

from collections import namedtuple
import time
import sys
import click
import wmi

TIMEOUT_SECONDS = 20

# static configuration
Config = namedtuple('Config', 'name dhcp ip subnetmask gateway')

configs = {
    'dhcp': Config('dhcp', True, None, None, None),
    'static': Config('static', False, '192.168.1.110', '255.255.255.0', '192.168.1.0')
}


nic_configs = wmi.WMI().Win32_NetworkAdapterConfiguration(IPEnabled=True)
nic = nic_configs[0]


def ip_address():
    ip = nic.wmi_property('IPAddress')
    return ip.value[0]


def subnetmask():
    subnet = nic.wmi_property('IPSubnet')
    return subnet.value[0]


def gateway():
    gateway = nic.wmi_property('DefaultIPGateway')
    return gateway.value[0]

def dhcp_enabled():
    dhcp = nic.wmi_property('DHCPEnabled')
    return dhcp.value


def config_active(config):
    if config.dhcp:
        return dhcp_enabled()
    return (config.ip == ip_address() and
            config.subnetmask == subnetmask() and
            config.gateway == gateway())


@click.command()
@click.option('--config', type=click.Choice(configs.keys()))
def set_nic(config):
    config_name = config
    config = configs[config]
    if config.dhcp:
        nic.EnableDHCP()
    else:
        nic.EnableStatic(IPAddress=[config.ip],SubnetMask=[config.subnetmask])
        nic.SetGateways(DefaultIPGateway=[config.gateway])

    t0 = time.perf_counter()

    while not abs(time.perf_counter() - t0) > TIMEOUT_SECONDS:
        if config_active(config):
            click.echo('Successfully changed config to {}.'.format(config_name))
            break
        time.sleep(1)
    else:
        click.echo('Timeout')

    click.echo('IP: {ip}\nSubnetmask: {subnetmask}\n'
               'Gateway: {gateway}'.format(
                    ip=ip_address(),
                    subnetmask=subnetmask(),
                    gateway=gateway()
                ))

if __name__ == '__main__':
    set_nic()

So this small script certainly isn't the top of the line but it was written pretty fast and serves me well.