Click here to Skip to main content
15,881,882 members
Articles / Desktop Programming / Windows Forms

Host Switcher

Rate me:
Please Sign up or sign in to vote.
4.67/5 (5 votes)
19 Jan 2011CPOL1 min read 31.6K   824   13  
Quickly and easily alternate between servers in the hosts file.
/*
 * Application: HostSwitcher.exe
 * 
 * Authors:  Daniel Liedke
 * 
 * Purpose: Quickly and easy change hosts file
 *  
 * ------------------------------------------------------------------------------------------
 * CHANGE LOG
 * ------------------------------------------------------------------------------------------
 * Date		    Author				Change Details 
 * ------------------------------------------------------------------------------------------
 * 06-15-2010   Daniel Liedke          Initial version created.
 * 
 */

using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace HostSwitcher
{
    public partial class MainScreen : Form
    {
        #region Class Variables/Structs

        private FileSystemWatcher fileWatcher;

        public struct stHost
        {
            public string HostDescription;
            public string HostComment;
            public string IP;
            public bool Selected;
        }

        #endregion

        #region Initialization

        public MainScreen()
        {
            InitializeComponent();
        }

        private void MainScreen_Load(object sender, EventArgs e)
        {
            CreateHostsFileWatcher();
            BuildHostsTray();
        }

        private void tmrUI_Tick(object sender, EventArgs e)
        {
            // Hides the main screen after load
            tmrUI.Enabled = false;
            this.Visible = false;
        }

        #endregion

        #region Parse Hosts and Create Host Tray

        private IList<stHost> ParseHostsFile(ref bool noHosts)
        {
            noHosts = true;
            IList<string> lineList = new List<string>();
            IList<stHost> hostList = new List<stHost>();

            try
            {
                // Reads all lines from hosts file
                FileInfo fileInfo = new FileInfo(GetHostsFilename());
                StreamReader sr = fileInfo.OpenText();
                while (sr.EndOfStream == false)
                {
                    string line = sr.ReadLine();
                    line = line.Trim();

                    //if (string.IsNullOrEmpty(line) == false)
                    {
                        lineList.Add(line.Replace("\t", " ").Replace("\r", " ").Replace("\n", " "));
                    }
                }
                sr.Close();

                // Creates a host list
                for (int f = 0; f < lineList.Count; f++)
                {
                    // If we found an host entry with a comment in the line before, ex:
                    //
                    // # DIT - x.acme.com       [host comment]
                    // #38.25.63.10				acme          [host ip]   [host address]
                    //
                    if (lineList[f].StartsWith("# ") &&
                        (f + 1) < lineList.Count &&
                        (StartWithNumberCommented(lineList[f + 1]) || StartWithNumber(lineList[f + 1])))
                    {
                        // Get host comment
                        string hostComment = lineList[f].Replace("# ", "");
                        
                        // Retrieve host details line
                        string hostDetailsLine = lineList[f + 1];
                        
                        // Get host IP
                        string hostIp = hostDetailsLine.Replace("#", "");
                        if (hostIp.IndexOf(" ") > -1)
                        {
                            hostIp = hostIp.Substring(0, hostIp.IndexOf(" "));
                        }
                                               
                        // Get host address
                        string hostAddress = string.Empty;
                        if ((hostDetailsLine.IndexOf(" ") > -1) && hostDetailsLine.IndexOf(" ") < hostDetailsLine.Length)
                        {
                            hostAddress = hostDetailsLine.Substring(hostDetailsLine.IndexOf(" ")).Trim();
                        }

                        // Creates the host description with comment, addresss and IP
                        string hostDescription = hostComment + " [" + hostAddress + " at " + hostIp + "]";
                        
                        // Check if host is not commented out
                        bool selected = StartWithNumber(hostDetailsLine);


                        // Search for repeated IP entries
                        bool hostAlreadyExists = false;
                        foreach (stHost hostItemSearch in hostList)
                        {
                            if (hostItemSearch.IP == hostIp)
                            {
                                hostAlreadyExists = true;
                            }
                        }

                        // Make sure we don´t add repeated IP entries
                        // And also only entries with host IP and host address
                        if (hostAlreadyExists == false &&
                            string.IsNullOrEmpty(hostIp) == false &&
                            string.IsNullOrEmpty(hostAddress) == false)
                        {
                            // Create and add new host object to the list
                            stHost hostItem = new stHost();
                            hostItem.HostDescription = hostDescription;
                            hostItem.HostComment = hostComment;
                            hostItem.IP = hostIp;
                            hostItem.Selected = selected;
                            hostList.Add(hostItem);

                            // If we found a single selected host, no hosts menu option can´t be enabled
                            if (selected)
                            {
                                noHosts = false;
                            }
                        }
                    }
                    else if ((StartWithNumberCommented(lineList[f]) || StartWithNumber(lineList[f])) &&
                        (f - 1) >= 0 &&
                        lineList[f-1].StartsWith("# ")==false)
                    {
                        // Parse strings in both formats:
                        //
                        // #102.54.94.97 rhino.acme.com # Rhino server     [host ip]  [host address] [host comment]
                        //
                        // #10.4.2.4 www.test1234567.com        [host ip]  [host address]
                        //

                        // Retrieve host ip
                        string hostIp = lineList[f].Replace("#", "");
                        if (hostIp.IndexOf(" ") > -1)
                        {
                            hostIp = hostIp.Substring(0, hostIp.IndexOf(" "));
                        }

                        // Gets host address and comment
                        string hostFullText = string.Empty;
                        if (lineList[f].IndexOf(" ") > -1)
                        {
                            hostFullText = lineList[f].Substring(lineList[f].IndexOf(" ") + 1).TrimStart();
                        }

                        // Gets only host address
                        string hostAddress = hostFullText;
                        if (hostFullText.IndexOf(" ") > -1)
                        {
                            hostAddress = hostFullText.Substring(0, hostFullText.IndexOf(" ")).Trim();
                        }

                        // Gets only host comment
                        string hostComment = string.Empty;
                        if (hostFullText.IndexOf("#") > -1 && ((hostFullText.IndexOf("#") + 1) < hostFullText.Length))
                        {
                            hostComment = hostFullText.Substring(hostFullText.IndexOf("#") + 1).Trim();
                        }

                        // Creates the host description with comment, addresss and IP
                        string hostDescription = hostComment + " [" + hostAddress + " at " + hostIp + "]";
                             
                        // Check if host is not commented out
                        bool selected = StartWithNumber(lineList[f]);


                        // Search for repeated IP entries
                        bool hostAlreadyExists = false;
                        foreach (stHost hostItemSearch in hostList)
                        {
                            if (hostItemSearch.IP == hostIp)
                            {
                                hostAlreadyExists = true;
                            }
                        }

                        // Make sure we don´t add repeated IP entries
                        // And also only entries with host IP and host address
                        if (hostAlreadyExists == false &&
                            string.IsNullOrEmpty(hostIp)==false &&
                            string.IsNullOrEmpty(hostAddress)==false)
                        {
                            // Create and add new host object to the list
                            stHost hostItem = new stHost();
                            hostItem.HostDescription = hostDescription;
                            hostItem.HostComment = hostComment;
                            hostItem.IP = hostIp;
                            hostItem.Selected = selected;
                            hostList.Add(hostItem);

                            // If we found a single selected host, no hosts menu option can´t be enabled
                            if (selected)
                            {
                                noHosts = false;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error parsing hosts file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return hostList;
        }

        private void BuildHostsTray()
        {
            try
            {
                // Parse current hosts file
                bool noHosts = false;
                IList<stHost> hostList = ParseHostsFile(ref noHosts);

                // Clear tray menu
                cmsHosts.Items.Clear();

                // Add default "No hosts" option
                System.Windows.Forms.ToolStripMenuItem menuItemNone = new System.Windows.Forms.ToolStripMenuItem();
                menuItemNone.Name = "";
                menuItemNone.Text = "[No hosts]";
                menuItemNone.Checked = noHosts;
                menuItemNone.MouseUp += new MouseEventHandler(menuItem_MouseUp);
                cmsHosts.Items.Add(menuItemNone);

                // Add menu separator
                System.Windows.Forms.ToolStripSeparator toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator(); ;
                toolStripMenuItem1.Size = new System.Drawing.Size(149, 6);
                cmsHosts.Items.Add(toolStripMenuItem1);

                // Add all commented host entries
                foreach (stHost host in hostList)
                {
                    System.Windows.Forms.ToolStripMenuItem menuItem = new System.Windows.Forms.ToolStripMenuItem();
                    menuItem.Name = host.IP;
                    menuItem.Text = host.HostDescription;
                    menuItem.Tag = host.HostComment;
                    menuItem.Checked = host.Selected;
                    menuItem.MouseUp += new MouseEventHandler(menuItem_MouseUp);
                    cmsHosts.Items.Add(menuItem);
                }

                // Add menu separator
                System.Windows.Forms.ToolStripSeparator toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
                toolStripMenuItem2.Size = new System.Drawing.Size(149, 6);
                cmsHosts.Items.Insert(cmsHosts.Items.Count, toolStripMenuItem2);

                // Add "View Hosts File" option
                System.Windows.Forms.ToolStripMenuItem viewHostsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
                viewHostsToolStripMenuItem.Name = "viewHostsToolStripMenuItem";
                viewHostsToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
                viewHostsToolStripMenuItem.Text = "&View Hosts File";
                viewHostsToolStripMenuItem.Click += new EventHandler(viewHostsToolStripMenuItem_Click);
                cmsHosts.Items.Insert(cmsHosts.Items.Count, viewHostsToolStripMenuItem);

                // Add menu separator
                System.Windows.Forms.ToolStripSeparator toolStripMenuItem3 = new System.Windows.Forms.ToolStripSeparator();
                toolStripMenuItem3.Size = new System.Drawing.Size(149, 6);
                cmsHosts.Items.Insert(cmsHosts.Items.Count, toolStripMenuItem3);

                // Add "Exit" application option
                System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
                exitToolStripMenuItem.Name = "exitToolStripMenuItem";
                exitToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
                exitToolStripMenuItem.Text = "&Exit";
                exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
                cmsHosts.Items.Insert(cmsHosts.Items.Count, exitToolStripMenuItem);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error creating tray menu: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region Update Hosts

        private void menuItem_MouseUp(object sender, MouseEventArgs e)
        {
            try
            {
                if (e.Button == MouseButtons.Left)
                {
                    // When left clicking menu, update hosts
                    ToolStripMenuItem itemSelected = ((ToolStripMenuItem)(sender));
                    string ipHost = itemSelected.Name;
                    UpdateHosts(ipHost);

                    // Uncheck all host items
                    foreach (ToolStripItem item in cmsHosts.Items)
                    {
                        if (item.GetType() == typeof(ToolStripMenuItem))
                        {
                            ((ToolStripMenuItem)item).Checked = false;
                        }
                    }

                    // Check selected host item
                    itemSelected.Checked = true;
                }
                else if (e.Button == MouseButtons.Right)
                {
                    // When right clicking menu, copy host name
                    ToolStripMenuItem itemSelected = ((ToolStripMenuItem)(sender));
                    Clipboard.SetText(GetHostAddress(itemSelected));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in tray menu mouse up: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private string GetHostAddress(ToolStripMenuItem menuItem)
        {
            string hostAddress = menuItem.Text;

            try
            {
                string tag = menuItem.Tag as string;

                //
                // Attempts to get server name from a string like
                // DIT - dit.acme.com
                //
                if (string.IsNullOrEmpty(tag) == false && tag.IndexOf(".") > -1)
                {
                    int f = 0;
                    for (f = tag.IndexOf("."); f >= 0; f--)
                    {
                        if (tag[f] == ' ')
                        {
                            break;
                        }
                    }
                    hostAddress = tag.Substring(f + 1);
                    if (hostAddress.IndexOf(" ") > -1)
                    {
                        hostAddress = hostAddress.Substring(hostAddress.IndexOf(" ")).Trim();
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error in GetHostAddress: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
             
            return hostAddress;
        }

        private void UpdateHosts(string ipHost)
        {
            try
            {
                StringBuilder sbHostsNew = new StringBuilder();

                // Read hosts file
                FileInfo fileInfo = new FileInfo(GetHostsFilename());
                StreamReader sr = fileInfo.OpenText();
                while (sr.EndOfStream == false)
                {
                    string line = sr.ReadLine();

                    // Check if we found selected host commented out
                    if (string.IsNullOrEmpty(ipHost) == false &&
                        line.Contains(ipHost) &&
                        line.StartsWith("#" + ipHost))
                    {
                        // Uncomment selected host
                        line = line.Substring(1);
                    }
                    else if (((string.IsNullOrEmpty(ipHost) == false) && (line.Contains(ipHost) == false)) ||
                               string.IsNullOrEmpty(ipHost) == true)
                    {
                        // Comment out other entries except already uncommend host entry
                        if (StartWithNumber(line))
                        {
                            line = "#" + line;
                        }
                    }
                    sbHostsNew.Append(line + "\r\n");
                }
                sr.Close();

                // Saves new host file and prevent file watcher from raising event
                fileWatcher.EnableRaisingEvents = false;
                TextWriter tw = new StreamWriter(GetHostsFilename());
                tw.Write(sbHostsNew.ToString());
                tw.Flush();
                tw.Close();
                fileWatcher.EnableRaisingEvents = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error updating hosts file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region Host File Watcher

        private void CreateHostsFileWatcher()
        {
            try
            {
                // Make sure to monitor hosts file for changes
                fileWatcher = new FileSystemWatcher();
                fileWatcher = new FileSystemWatcher(GetHostsPath());
                fileWatcher.Changed += new FileSystemEventHandler(fileWatcher_Changed);
                fileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
                fileWatcher.EnableRaisingEvents = true;
                fileWatcher.Filter = "hosts";
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error monitoring hosts file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void fileWatcher_Changed(object sender, FileSystemEventArgs e)
        {
            try
            {
                // Wait a bit for file to be saved and reload
                // hosts menu when file is changed externally
                //
                System.Threading.Thread.Sleep(700);
                if (InvokeRequired == false)
                {
                    BuildHostsTray();
                }
                else
                {
                    Invoke(new FileSystemEventHandler(fileWatcher_Changed), sender, e);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error monitoring hosts file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region View Hosts File

        private void viewHostsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                // Shows notepad with hosts file
                ProcessStartInfo psi = new ProcessStartInfo("notepad.exe");
                psi.Arguments = GetHostsFilename();
                Process.Start(psi);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error showing hosts file: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region Exit

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                //
                // When exitting and No Hosts is not selected
                // ask user if he would like to keep host configuration
                // otherwise clear hosts
                //
                if (((ToolStripMenuItem)cmsHosts.Items[0]).Checked == false)
                {
                    DialogResult dialogResult = MessageBox.Show("Keep current host configuration ?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
                    if (dialogResult == DialogResult.No)
                    {
                        UpdateHosts(string.Empty);
                    }
                }
                Application.Exit();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error exitting application: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        #endregion

        #region General Methods

        private string GetHostsPath()
        {
            // Gets dynamic hosts path from system folder
            string systemPath = Environment.GetFolderPath(Environment.SpecialFolder.System);
            string hostsPath = Path.Combine(systemPath, @"drivers\etc");
            return hostsPath;
        }

        private string GetHostsFilename()
        {
            // Creates full host filename
            string hostsFileName = Path.Combine(GetHostsPath(), "hosts");
            return hostsFileName;
        }

        private bool StartWithNumber(string str)
        {
            // Check if string starts with an ip number
            Regex regex = new Regex(@"^\d{1}");
            return regex.IsMatch(str);
        }

        private bool StartWithNumberCommented(string str)
        {
            // Check if strings starts with a commented ip number
            Regex regex = new Regex(@"^#{1}\d{1}");
            return regex.IsMatch(str);
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Brazil Brazil
I started development 37 years from now, since MSX basic. Started Windows programming with VB 2.0 and Web programming with ASP 3.0. Then I built Windows Forms, Web Applications, NT services and WPF applications using Microsoft.NET. I am MCP in Visual Basic 6.0, MCAD and MCSD.NET in Framework 1.1, MCPD Web in Framework 2.0, MCTS in .NET 3.5 workflow, MCTS in .NET 3.5 communication foundation, windows presentation foundation and MVC applications. Built MVC Web Application and WCF services using Micro Services architecture proposed by me. Working with AI projects to improve the business performance and customer experience. Besides programming I love running, swimming, reading and movies.

Comments and Discussions