Click here to Skip to main content
15,881,089 members
Articles / Programming Languages / C#

Network Assistant for mobile PCs

Rate me:
Please Sign up or sign in to vote.
4.86/5 (3 votes)
21 Apr 2007Public Domain8 min read 40.8K   366   33   8
A small tool that reacts to change in your network environment and changes your settings accordingly.

Introduction

I don't know about you, but one of the things that bores me the most about being a "MobilePC" user is that I have to do the same things again and again and again and again…

So, this little app is what I have done in an attempt to remove the pain of being a mobile user. Its only purpose is to react to changes in your network environment and try to set your preferences accordingly. Let's say, for the sake of the example, that you use your laptop in 3 distinct places (at home, at work, and in the bus). You certainly change your default printer about 99 times a week, probably swear about that …. proxy you have at work, etc.

Wouldn't it be cool if your laptop just adapted to your environment?

NB: this article is not about the code in itself, but about the application, and how to use it. The only "tricky" (but really easy) bit of code is about the Network Awareness API (see the corresponding paragraph).

Definitions

Some definitions about the terms that I will use in this article.

NetworkConfiguration

A network configuration is an environment in which your MobilePC can be. Examples of NetworkConfigurations are : « At Home », « At work », « At client X », « Disconnected ». A NetworkConfiguration is defined by its tests – which identifies the state of network settings which identifies the environment – and its netlets –which are commands to execute in order to configure the system.

Tester

A tester is a class that allows to determine if your MobilePC is in a NetworkConfiguration. Examples : « Is My PC connected to DHCP server 192.168.0.1 ?» A NetworkConfiguration is called « active » if all of it's tests pass.

Netlet

A netlet is a command that is executed when a NetworkConfiguration is activated or disactivated. Its purpose is to set the environment up, such as changing the default printer, mapping a network drive or moving files to the desktop/start menu.

How does it work?

A small, notification-area-based application runs in the background of your session and reacts to changes in your network environment. Using a set of rules/Testers, it selects from the configurations that you have set-up the one that is currently active, and configures your systems accordingly.

Let's say that you use your laptop in three environments: at home, at work, and on the bus (or anywhere else without a proper network connection); between those three environments, you may want to change some of your settings such as your default printer, the proxy used to connect to the Internet, etc. What you need is something like:

Home Office Everywhere else
(when disconnected)
Use my inkjet printer Use a big laser printer Print to PDF files
Connect to the internet through my ISP router Use my corporate proxy
Map Z: to \\family\share
Get shortcuts to my server or applications on my desktop

You just have to configure three distinct NetworkConfigurations, and try to define what distinguishes one from another. When you have set-up the conditions (Testers) that uniquely identifies one configuration, you may add one or more commands (Netlets) which will change the state of your system.

Home Office Everywhere else
(when disconnected)
When those conditions are met (Testers)
There is a network present There is a network present There is no network connection
My DHCP Server is 192.168.0.254 My DHCP Server is 10.0.38.253
My DNS suffix is mycompany.com
What to do ? (Netlets)
Change default printer to My Inkjet Change default Printer to \\Server\Printer2 Change default printer to PDFPrint
Map Drive Z: to \\family\share
Copy *.rdp to my Desktop
Set IE Proxy to 10.0.38.254

A netlet will change to the desired state when a configuration is activated and revert back to the previous state when needed, so you don't have to worry about removing the proxy on IE on the Home profile if it is not set by default.

The Network Awareness API

The core of this software is the Network Awareness API which is shipped with Windows XP & Vista. For managed users, this API is available thru the System.Net.NetworkInformation namespace. The NetworkChange static class in this namespace contains two interesting events:

  • NetworkAvailabilityChanged which is fired when your MobilePC connects (or disconnects) to any network
  • NetworkAddressChanged fired when any of your network adapters receives a new IP address.

Using these events, it's rather easy to make an application respond to network changes (NB: this is not the code used by the application, but a rather heavily stripped down version for easier understanding):

C#
private class MyAssistant
{
 public void Initialize()
 {
  NetworkChange.NetworkAddressChanged +=
   new NetworkAddressChangedEventHandler(NetworkChange_NetworkAddressChanged);
 }
 bool IsConnected
 {
  get
  {
   return NetworkInterface.GetIsNetworkAvailable();
  }
 }
 void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
 {
  if (IsConnected)
   ChangeDefaultPrinter("MyInkjet");
  else
   ChangeDefaultPrinter("PDFPrinter");
 }
}

I've used the NetworkAddressChanged event because I need the IP Address to be set for some tests (on DHCP or DNS settings). This code sample introduces the other important class of this namespace NetworkInterface which allows getting the settings from your network cards (and other devices). For this application, we need to find if a particular DHCP or DNS is used, so we'll iterate through all of our network interfaces, get their IP-related parameters and look for a known server:

C#
void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
{
 if (!IsConnected)
  ChangeDefaultPrinter("PDFPrint");
 else if(FindDhcp(IPAddress.Parse("192.168.0.254")))
  ChangeDefaultPrinter("MyInkjet");
 else if(FindDhcp(IPAddress.Parse("10.0.38.253")))
  ChangeDefaultPrinter(@"\\Server\Printer2");
}
private bool FindDhcp(IPAddress dhcpAddress)
{
 foreach (NetworkInterface card in NetworkInterface.GetAllNetworkInterfaces())
 {
  IPInterfaceProperties props = card.GetIPProperties();
  foreach (IPAddress cardDhcp in props.DhcpServerAddresses)
  {
   if (cardDhcp.Equals(dhcpAddress))
    return true;
  }
 }
 return false;
}

Configuration

All the configuration of this assistant is done by through an XML-based settings file which you can edit from your start menu (Start>All Programs>Network Assistant v0.5>Edit your NetworkConfigurations). It's format is rather simple:

  • Each NetworkConfiguration must be a child of the root Config element and must have a name attribute
  • A NetworkConfiguration should have 2 child elements: Tests and Netlets
  • In Tests, you can put one of the following elements:
    • IsConnected
    • DnsServer
    • DnsSuffix
    • DhcpServer
  • In Netlets, the following children are allowed:
    • DefaultPrinter
    • ConnectNetworkDrive
    • CopyFiles
    • IEProxy
    • (more netlets will be added later)

A test element (IsConnected, DnsServer…) always has the same format:

XML
<TestName value="valueToTest" />
Test name Value parameter Remark
IsConnected "true" or "false" If you want the test to pass when a network is available use "true", and if you want to test if the MobilePC is in a disconnected state use "false"
DhcpServer IP address You must use an IP address (192.168.0.1). Using a computer hostname is not supported
DnsServer IP address (idem)
DnsSuffix DNS suffix Ex : "carbenay.info"

The Tests node for the Home configuration is:

XML
<Tests>
 <IsConnected value="true" />
 <DnsServer value="192.168.0.1" />
</Tests>

The netlets have not the same "standard" parameter so each one is different.

NetletName Parameter Remarks
DefaultPrinter printerName="{PrinterName}"
CopyFiles sourceFolder="{Path}" The {Path} parameter can include environment variables (such as %USERNAME%, %APPDATA% …) and can also use: %DESKTOP% : path to the current user's desktop (more aliases will be added)
destinationFolder="{Path}" Idem
searchPattern="{SearchPattern}" i.e.: "*.rdp", "*.lnk"…
ConnectNetworkDrive localDrive="{DriveLetter}" Drive letter (in the format X:) on which to mount the network share
remotePath="{RemotePath}" Path to the network share in UNC format (i.e.: \\server\share)
OpenFirewallPort port="{PortNumber}" port number.
This netlet only works on Windows XP. Vista would require Privilege elevationprotocol="{Protocol}" Protocol can be either "TCP" or "UDP"

For example: the Home configuration's Netlets element is shown below:

XML
<Netlets>
 <DefaultPrinter printerName="MyInkjet" />
 <CopyFiles
  sourceFolder="%LOCALAPPDATA%\NetworkAwareAssistant\Home\CopyFiles\"
  destinationFolder="%DESKTOP%"
   searchPattern="*.rdp"
   />
 <ConnectNetworkDrive
    localDrive="J:"
    remotePath="\\FamilyServer\Share" />
</Netlets>

A future version of NetworkAssistant will include a Control Panel application, but for this first release, you'll have to edit your settings manually.

Extensibility

Extending this app is rather simple: you just have to create classes that implement INetlet, put your assembly in the application folder (or in the GAC), and add a reference to it in the NetworkAwareAssistant.xml file.

Implementing a netlet requires you to implement an interface with 5 methods (sample code comes from the ChangeDefaultPrinterNetlet class):

  • void Initialize(string configurationName, XmlElement config): called when the configuration file is parsed. The configurationName parameters will be set to the name of the parent NetworkConfiguration, and the config parameter will be the XmlNode of your Netlet in the file.

    C#
    public void Initialize(string stateName, System.Xml.XmlElement config)
    {
     if (config == null)
      throw new ArgumentNullException("config");
     _defaultToSet = config.GetAttribute("printerName");
    }

  • void Connect(): called when the NetworkConfiguration is activated. There you should perform whatever your Netlet is supposed to do.

    C#
    public void Connect()
    {
     if (string.IsNullOrEmpty(_defaultToSet))
      return;
     using (ManagementObjectSearcher sr = new ManagementObjectSearcher(
        "select * from Win32_Printer where default=1 or name=\""
            + _defaultToSet + "\""))
     {
      ManagementObject oldPrinter;
      ManagementObject newPrinter;
      string currentDefaultName;
      FindPrinters(sr,
       _defaultToSet,
       out oldPrinter,
       out newPrinter,
       out currentDefaultName);
      if (oldPrinter != newPrinter)
      {
       try
       {
        newPrinter.InvokeMethod("SetDefaultPrinter", new object[0]);
        _defaultToRestore = currentDefaultName;
       }
       catch (Exception e)
       {
       throw new Exception("Unable to set the default printer to " +
        _defaultToSet);
       }
      }
     }
    }

  • void Disconnect(): called when a NetworkConfiguration is deactivated. This method must revert the environment in its previous state if possible. In ChangeDefaultPrinterNetlet, this method is quite similar to Connect.

  • void SaveState(System.Xml.XmlElement elmToSaveTo): provides a way for the system to remember the current state of the NetworkConfiguration. This method (with Load) allows for the application to shutdown and restart. In this method you should put any data that you may need to restore the netlet to its current state.

    C#
    public void SaveState(System.Xml.XmlElement elmToSaveTo)
    {
        elmToSaveTo.SetAttribute("oldDefault", _defaultToRestore);
        elmToSaveTo.SetAttribute("newDefault", _defaultToSet);
    }

  • void LoadState(System.Xml.XmlElement elmToLoadFrom): Loads the netlet state from a previously saved state. These two methods are only meant to do some basic serialization: they should not (except if it really makes sense for your netlet) make any changes to the system.

    C#
    public void LoadState(System.Xml.XmlElement elmToLoadFrom)
    {
        _defaultToRestore = elmToLoadFrom.GetAttribute("oldDefault");
        _defaultToSet = elmToLoadFrom.GetAttribute("newDefault");
    }

When your class is ready, there are two more things to do:

  • Add a NetletAttribute to the class: the name parameter of this attribute will be used to identity your netlet's configuration nodes in the NetworkAwareAssistant.xml file.

    C#
    [Netlet("TraceConfigChange")]
    public class TraceChangeNetlet : INetlet
    {
    ...
    }
  • Add a reference to your assembly and class in NetworkAwareAssistant.xml by adding a new /Config/Assemblies/Add node and add your netlet to a NetworkConfiguration.

    XML
    <Config>
     <Assemblies>
      <Add name="MyExtensionAssembly"/>
     </Assemblies>
     ...
     <Netlets>
      <TraceConfigChange />
     <Netlets>
     ...
    </Config>

Here is the sample code for a Netlet that just writes a trace on Connect/Disconnect:

C#
[Netlet("TraceConfigChange")]
public class TraceChangeNetlet : INetlet
{
 private string _currentConfig = null;
 public void Initialize(string stateName, System.Xml.XmlElement config)
 {
  _currentConfig = stateName;
 }
 public void Connect()
 {
  Trace.TraceInformation("NetworkConfiguration " + 
                    _currentConfig +" activated");
 }
 public void Disconnect()
 {
  Trace.TraceInformation("NetworkConfiguration " + 
                    _currentConfig +" de-activated");
 }
 public void LoadState(System.Xml.XmlElement elmToLoadFrom)
 {
 }
 public void SaveState(System.Xml.XmlElement elmToSaveTo)
 {
 }
}

History

  • 21 Apr 2007: First release
  • 25 Apr 2007: Added a command to open port in firewall for Windows XP (Vista firewall would need a privilege elevation). Thanks for suggesting this goes to sides_dale.

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication


Written By
Web Developer
France France
I'm french, do I need to say more ?

Comments and Discussions

 
QuestionHard Coded IP Addresses Pin
sides_dale22-Apr-07 15:38
sides_dale22-Apr-07 15:38 
AnswerRe: Hard Coded IP Addresses Pin
mcarbenay23-Apr-07 5:39
mcarbenay23-Apr-07 5:39 
GeneralRe: Hard Coded IP Addresses Pin
Gavin Roberts24-Apr-07 0:23
Gavin Roberts24-Apr-07 0:23 
You could try pinging the Gateway for each hardware configuration or use WMI.
GeneralRe: Hard Coded IP Addresses Pin
mcarbenay24-Apr-07 0:32
mcarbenay24-Apr-07 0:32 
GeneralRe: Hard Coded IP Addresses Pin
Gavin Roberts24-Apr-07 0:37
Gavin Roberts24-Apr-07 0:37 
GeneralRe: Hard Coded IP Addresses Pin
mcarbenay24-Apr-07 0:52
mcarbenay24-Apr-07 0:52 
GeneralRe: Hard Coded IP Addresses Pin
Gavin Roberts24-Apr-07 1:17
Gavin Roberts24-Apr-07 1:17 
GeneralRe: Hard Coded IP Addresses Pin
mcarbenay24-Apr-07 23:00
mcarbenay24-Apr-07 23:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.