Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

NetProfiles - Multiple IP Profiles Made Easy

0.00/5 (No votes)
15 Jul 2010 1  
A utility to manage multiple IP profiles (home/work/grandma's etc...)

Introduction

When I worked for a network services company a few years back, we had to visit up to ten sites per day, each having their own distinct IP schemes. It was a constant pain to reconfigure network connections every time I moved between sites or subnets. I wrote this program to handle that task and keep track of the different settings for each of our customers. In this article, I will discuss several topics including some easy ways in which you can add a little style to your basic Windows Forms.

Application Interface

For this application, I chose to use a borderless form. In my opinion, it is a quick and easy way to add an aesthetic touch to your app. The can be done programmatically in the code of your form using the following statement:

this.FormBorderStyle = FormBorderStyle.None;

More information is presented on this below.

The Application Main Window

Main_Window.JPG

Edit Profile Window

profile_window.JPG

The Code and Concepts Behind the Application

Manipulating the Windows Registry

The Microsoft.Win32 namespace provides access to the RegistryKey class which allows you to manipulate the Windows registry. Three methods of the RegistryKey class are utilized in this application, OpenSubKey(), GetValue() and SetValue(). The code below illustrates how each of the aforementioned methods can be used.

In the following code block, I create the object Reg and set it to reference the HKEY_LOCAL_MACHINE hive of the registry, then navigate to a subkey "SOFTWARE\AntiDesign\NetProfiles".

 //read settings from the registry
 RegistryKey Reg = Registry.LocalMachine;
 Reg = Reg.OpenSubKey("Software\\AntiDesign\\NetProfiles", true); 

Below, I create another RegistryKey object from a subkey of the Reg object using the OpenSubKey() method. The string currProfile is assigned to using the GetValue() method of the RegistryKey class.

 //get current profile to see if we need to remove static routes.
 RegistryKey adapter = Reg.OpenSubKey("__Adapters\\" + cboSelectAdapter.Text, true);
 string currProfile = adapter.GetValue("CurrentProfile").ToString();

The SetValue() method is called in this instance to store a string representation of your IP address in the registry. As you can see from the example below, the Type being stored is selected using an Enum, RegistryValueKind.

//save a setting into the registry
Reg.SetValue("IPAddress", txtIPAddress.Text, RegistryValueKind.String);  

Enumerating your Network Adapters

The System.Net namespace provides numerous classes related to networking. This project only utilizes the NetworkInterface class's GetAllNetworkInterfaces() method. GetAllNetworkInterfaces() returns an array of NetworkInterface objects. I iterate through each of the objects in the array, checking the NetworkInterfaceType property so that only Ethernet and 802.11 interfaces are listed.

//Enumerate current system's network adapters and store results in a ComboBox
foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
{
    // Only get ethernet adapters
    if (netInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet | 
         netInterface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)
    {
         cboSelectAdapter.Items.Add(netInterface.Name);
    }
}
try
{
    cboSelectAdapter.SelectedIndex = 0;
}
catch { }

Applying IP Settings Programmatically

Windows provides a command line tool for changing your network settings called netsh. Rather than reinvent the wheel, it serves our purpose to call this utility transparently to accomplish this task. To do this, I am going to use the System.Diagnostics.Process class. Configuration of the process is done through Process.StartInfo. In the example, I define the following properties:

  • FileName (string)
  • UseShellExecute (bool) - Use the shell to launch the program? This value must be false to redirect IO or hide the console window.
  • CreateNoWindow (bool) - Should the process be run in a hidden window?
  • Arguments (string) - Any command line arguments to be passed to the application

After the Start() method is called and the process begins to execute, we also call the WaitForExit() method to stop execution until netsh.exe has finished modifying the IP settings. The netsh object is reused to set the DNS servers after changing the Arguments property.

//build the argument strings for netsh.exe
string argsIP, argsDNS;

argsIP = "interface ip set address name=\"" + AdapterName + "\" static " +
         ipAddress + " " + subnetMask + " " + gateway + " 1";
                    
argsDNS = "interface ip set dns name=\"" + AdapterName + "\" static " + dnsServer;
                    
//apply the changes
Process netsh = new Process();
netsh.StartInfo.FileName = "netsh.exe";
netsh.StartInfo.UseShellExecute = false;
netsh.StartInfo.CreateNoWindow = true;
netsh.StartInfo.Arguments = argsIP;

netsh.Start();
netsh.WaitForExit();

//Add the dns server
netsh.StartInfo.Arguments = argsDNS;
netsh.Start();
netsh.WaitForExit();
netsh.Dispose();

Using Embedded Fonts

Embedded fonts are another easy way to give your application that "customized" look without too much trouble or added code. Please note that embedding resources in your program can make the size of your application increase drastically, so if executable size is a major concern, then you may want to skip this step.

To begin embedding fonts, you must add use Interop to import gdi32.dll. A method prototype needs to be declared for AddFontMemResourceEx(). A PrivateFontCollection will be used to hold the fonts stored in memory.

[System.Runtime.InteropServices.DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont,
     IntPtr pdv, [System.Runtime.InteropServices.In] ref uint pcFonts);

public static PrivateFontCollection PFC = new PrivateFontCollection();  

Due to the nature of the Interop method being called, you have to wrap the code in an unsafe structure.

//
// ♠ get Ravie font from our embedded resources
//
try
{
    unsafe
    {
        fixed (byte* pFontData = Properties.Resources.RAVIE)
        {
            uint nil = 0;
            PFC.AddMemoryFont((IntPtr)pFontData, Properties.Resources.RAVIE.Length);
            AddFontMemResourceEx((IntPtr)pFontData,
               (uint)Properties.Resources.RAVIE.Length, IntPtr.Zero, ref nil);
        }
    }
}
catch
{
    MessageBox.Show("Ravie font was not loaded.");
}

Here is an example of how to use our embedded font for the Label3 Font property. If more than one font has been added to the PrivateFontCollection, you will need to iterate through the Families[i].Name properties to get the correct index. In the example below, it assumes that only one font is in the PrivateFontCollection.

//
// ♠ Set title bar to use Ravie Font
//
label3.Font = new Font(PFC.Families[0], (float)10); //Font size is 10 pt

Borderless Forms

I will quite often use borderless forms because it gives the "customized" look to an application and requires very little effort. You will however, have to add a few lines of code to allow your application to be moved around the screen. This is accomplished by adding MouseDown and MouseMove event handlers to the object(s) that you wish to be able to click and drag from.

The following code is inserted in the MouseDown events for each object that you wish to use as a drag point. The variable e is of type MouseEventArgs and contains two properties that are useful for us, e.X and e.Y, which tell us the X and Y coordinates of the mouse click. These values are stored in public int variables, x and y.

//add the following code to the MouseDown events
//x and y are public int values used to track click position
if (e.Button == MouseButtons.Left)
{
    x = e.X;
    y = e.Y;
}

The following code needs to be inserted into the MouseMove event handler code for the objects that will be used as drag points. It uses the current mouse position and the x and y variables that were populated during the MouseDown event to relocate the form.

//add the following code to your MouseMove Events
if (e.Button == MouseButtons.Left)
{
    this.Left += (e.X - x);
    this.Top += (e.Y - y);
}    

Conclusion

Little tweaks such as ensuring a font is available (embedding) and removing the borders from your forms can go a long way as far as user experience is concerned. The version of the program that I have uploaded does not contain the Ravie Font and isn't fully implementing embedded fonts. (I started, but ran out of time on this one...)

Note: Using netsh.exe on Vista can take a while while Windows "discovers?" your network connection. This seems to be resolved in Windows 7 and wasn't an issue in XP.

Final Thought

I still use this application on both of my laptops that I carry with me to and from work. Although I no longer spend as much time at client sites, it still saves time switching from static IP (work) and DHCP (home).

History

  • 7-14-2010 - Article posted

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here