[.NET][C#] Manager with singleton for manipulate the Windows Hosts File
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace Framework
{
public class ManagerHostFile
{
#region singleton
private static ManagerHostFile instance = null;
private static readonly object padlock = new object();
ManagerHostFile()
{
}
public static ManagerHostFile Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new ManagerHostFile();
}
hostList = ParseHostsFile(ref noHosts);
return instance;
}
}
}
#endregion singleton
private IList<stHost> hostList = new IList<stHost>();
#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
private struct stHost
{
public string HostDescription;
public string HostComment;
public string IP;
public bool Selected;
}
///
/// Parse Windows Host File
///
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)
{
throw ex;
}
return hostList;
}
/// <summary>
/// Update HostFile
/// </summary>
/// <param name="ipHost"></param>
public 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
TextWriter tw = new StreamWriter(GetHostsFilename());
tw.Write(sbHostsNew.ToString());
tw.Flush();
tw.Close();
}
catch (Exception ex)
{
throw ex;
}
}
}
}