I have finally got it, my Location Switcher.
First, some background. I use my laptop both at work, and at home. At work, I use a static IP and a second monitor @ 1024x768. At home, I use DHCP and a second monitor @ 1280x1024. So I wake up, go do some work, then go to work, change the settings, then go home and have to change them again. It wasn't long before this got REALLY annoying. For small utilities like this, I much prefer to build versus buy. It is fun. I figured there had to be a way to automate this process. It took a lot of digging around, but I finally got it. I now have an icon in the task tray, which has a context menu with the options I need. I originally had a Console app, but this just seemed easier.
The first menu item, Location, allows me to select a preconfigured location. When I go to work, I select Work, and it sets my static IP, and secondary monitor resolution. When I go home, it sets my network card to DHCP, and adjusts the second monitor. It is almost too easy. The Resolution item allows me to manually set specific resolutions for either the primary or secondary monitor. The Network option is not yet populated. Configure allows me to set up pre-defined configurations, like Work and Home. Finally Exit allows me to shut down the program in case I ever need to free up the minimal resources it is using because I am running low on the 2GB of memory I have installed.
Most of what I needed to do I found in the following WMI classes:
- Win32_NetworkAdapter
- Win32_NetworkAdapterConfiguration
- MicrosoftDNS_Server
For the monitors, I had to dig into the Windows API, yuck. I ended up using three methods in the user32.dll library;
- EnumDisplaySettings
- ChangeDisplaySettingsEx
- EnumDisplayDevices
For the configuration, I defined a schema (probably overkill), and used MSDataSetGenerator to generate a strongly-typed class. This allowed me to load a config from disk.
<?xml version="1.0" encoding="utf-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:cfg="http://tempuri.org/config.xsd" targetNamespace="http://tempuri.org/config.xsd" elementFormDefault="qualified">
<element name="config" type="cfg:tConfig" />
<complexType name="tConfig">
<choice maxOccurs="unbounded">
<element name="network" type="cfg:tNetwork" maxOccurs="unbounded" />
</choice>
</complexType>
<complexType name="tNetwork">
<sequence>
<element name="nameservers" type="cfg:tNameservers" />
<element name="adapter" type="cfg:tAdapter" />
<element name="routes" type="cfg:tRoutes" nillable="true" maxOccurs="unbounded" />
<element name="display" type="cfg:tDisplay" nillable="true" maxOccurs="1" />
</sequence>
<attribute name="id" type="string" />
<attribute name="name" type="string" />
</complexType>
<complexType name="tAdapter">
<attribute name="type" type="cfg:tNetworkType" use="required" />
<attribute name="ipaddress" type="string" use="optional" />
<attribute name="subnet" type="string" use="optional" />
<attribute name="gateway" type="string" use="optional" />
</complexType>
<complexType name="tNameservers">
<sequence>
<element name="nameserver" type="cfg:tNameserver" nillable="true" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="tNameserver">
<simpleContent>
<extension base="string" />
</simpleContent>
</complexType>
<simpleType name="tNetworkType">
<restriction base="string">
<enumeration value="static" />
<enumeration value="dynamic" />
</restriction>
</simpleType>
<complexType name="tRoutes">
<sequence>
<element name="route" type="string" minOccurs="0" maxOccurs="unbounded" />
</sequence>
</complexType>
<complexType name="tDisplay">
<sequence minOccurs="0" maxOccurs="1">
<element name="h" type="int" minOccurs="0" maxOccurs="1" />
<element name="v" type="int" minOccurs="0" maxOccurs="1" />
</sequence>
<attribute name="enabled" type="boolean" use="required" />
</complexType>
</schema>
So there it is. If I get any interest, I might publish the source code. There are still features to add. For example, I would love to have it auto-detect the network and automatically switch.