' ***********************************************************************
' Author : Elektro
' Last Modified On : 08-11-2014
' ***********************************************************************
' <copyright file="HostsFile.vb" company="Elektro Studios">
' Copyright (c) Elektro Studios. All rights reserved.
' </copyright>
' ***********************************************************************
#Region " Usage Examples "
'Public Class HostsFileTestClass
'
' Private Sub HostsFileTestHandler() Handles MyBase.Shown
'
' ' Instance the HostsFile Class.
' Dim Hosts As New HostsFile()
'
' ' Set a new mapping.
' Dim Mapping As New HostsFile.MappingInfo
' With Mapping
' .HostName = "cuantodanio.es"
' .IP = Hosts.LOCALHOST ' "127.0.0.1"
' .Comment = "Test mapping comment."
' End With
'
' With Hosts
'
' ' Delete the Host file.
' If .FileExists Then
' .FileDelete()
' End If
'
' ' Create a new one Hosts file.
' .FileCreate()
'
' ' Add some new mappings.
' .Add(Mapping)
' .Add(HostName:="www.youtube.com", IP:=.LOCALHOST, Comment:="Test mapping comment")
'
' ' Check if a mapping exists.
' If .IsMapped(Mapping) Then
' ' Disable the mapping.
' .Disable(Mapping)
' End If
'
' ' Check if an existint mapping is disabled.
' If .IsDisabled("www.youtube.com") Then
' ' Remove the mapping.
' .Remove("www.youtube.com")
' End If
'
' ' Open the HOSTS file with the specified text-editor.
' .FileOpen("C:\Program Files\Sublime Text\sublime_text.exe")
'
' End With
'
' ' Get the IP of a mapped Hostname.
' MessageBox.Show("cuantodanio.es: " & Hosts.GetMappingFromHostname("cuantodanio.es").IP)
'
' ' Get all the hostname mappings
' Dim Mappings As List(Of HostsFile.MappingInfo) = Hosts.GetMappings()
' For Each MappingInfo As HostsFile.MappingInfo In Mappings
'
' Dim sb As New System.Text.StringBuilder
' With sb
' .AppendLine(String.Format("Hostname...: {0}", MappingInfo.HostName))
' .AppendLine(String.Format("IP Address.: {0}", MappingInfo.IP))
' .AppendLine(String.Format("Comment....: {0}", MappingInfo.Comment))
' .AppendLine(String.Format("Is Enabled?: {0}", Not MappingInfo.IsDisabled))
' End With
'
' MessageBox.Show(sb.ToString, "HostsFile Mappings", MessageBoxButtons.OK, MessageBoxIcon.Information)
'
' Next MappingInfo
'
' ' Get all the hostname mappings that matches an ip address
' Dim MappingMatches As List(Of HostsFile.MappingInfo) = Hosts.GetMappingsFromIP(Hosts.LOCALHOST)
'
' End Sub
'
'End Class
#End Region
#Region " Imports "
Imports System.IO
Imports System.Net
Imports System.Text
'Imports System.Text.RegularExpressions
#End Region
#Region " Hosts File "
''' <summary>
''' Manages the Windows HOSTS file to map Hostnames to IP addresses.
''' </summary>
Public Class HostsFile
#Region " Constructors "
''' <summary>
''' Initializes a new instance of the <see cref="HostsFile"/> class.
''' </summary>
''' <param name="HOSTSLocation">
''' Optionaly indicates a custom Hosts file location.
''' Default value is 'X:\Windows\System32\Drivers\etc\hosts'.
''' </param>
Public Sub New(Optional ByVal HOSTSLocation As String = Nothing)
If Not String.IsNullOrEmpty(HOSTSLocation) Then
Me._HOSTSLocation = HOSTSLocation
End If
End Sub
''' <summary>
''' Prevents a default instance of the <see cref="HostsFile"/> class from being created.
''' </summary>
Private Sub New()
End Sub
#End Region
#Region " Properties "
''' <summary>
''' The Hosts file location.
''' </summary>
''' <value>The Hosts file location.</value>
Public ReadOnly Property HOSTSLocation As String
Get
Return _HOSTSLocation
End Get
End Property
Private SysDir As String = Environment.GetFolderPath(Environment.SpecialFolder.System)
Private _HOSTSLocation As String = Path.Combine(SysDir, "Drivers\etc\hosts")
''' <summary>
''' The Hosts file encoding.
''' The encoding must be <see cref="Encoding.Default"/> (ANSI) or <see cref="Encoding.UTF8"/> (UTF-8 without BOM),
''' otherwise the entries will be ignored by Windows.
''' </summary>
''' <value>The Hosts file encoding.</value>
Public Property HOSTSEncoding As Encoding
Get
Return _HOSTSEncoding
End Get
Set(ByVal value As Encoding)
Me._HOSTSEncoding = value
End Set
End Property
Private _HOSTSEncoding As Encoding = Encoding.Default
''' <summary>
''' Gets or sets the default 'LocalHost' IP address.
''' In most computers the default address is '127.0.0.1'.
''' </summary>
''' <value>The default LocalHost.</value>
Public Property LOCALHOST As String
Get
Return Me._LOCALHOST
End Get
Set(ByVal value As String)
Me._LOCALHOST = value
End Set
End Property
Private _LOCALHOST As String = "127.0.0.1"
''' <summary>
''' Gets the default Hosts file header.
''' </summary>
Private ReadOnly HostsHeader As String =
<a><![CDATA[
# Copyright (c) 1993-2009 Microsoft Corp.
#
# This
is a sample HOSTS
file used by Microsoft TCP
/IP
for Windows.
#
# This
file contains the mappings
of IP addresses
to host names.
Each# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
]]></a>.Value
#End Region
#Region " Types "
#Region " MappingInfo "
''' <summary>
''' Specifies info of a HOSTS file mapping.
''' </summary>
Public Class MappingInfo
''' <summary>
''' Gets or sets the hostname.
''' </summary>
''' <value>The hostname.</value>
Public Property HostName As String
''' <summary>
''' Gets or sets the IP address.
''' </summary>
''' <value>The IP address.</value>
Public Property IP As String
''' <summary>
''' Gets or sets the mapping comment.
''' </summary>
''' <value>The mapping comment.</value>
Public Property Comment As String
''' <summary>
''' This value is reserved.
''' Gets a value indicating whether the mapping is disabled in the HOSTS file.
''' </summary>
''' <value><c>true</c> if the mapping is disabled, <c>false</c> otherwise.</value>
Public Property IsDisabled As Boolean
End Class
#End Region
#End Region
#Region " Public Methods "
''' <summary>
''' Adds a new mapping.
''' </summary>
''' <param name="HostName">Indicates the Hostname.</param>
''' <param name="IP">Indicates the IP address.</param>
''' <param name="Comment">Indicates a comment for this mapping.</param>
''' <exception cref="System.IO.FileNotFoundException">"Hosts file not found."</exception>
''' <exception cref="System.FormatException">Invalid IP adress.</exception>
''' <exception cref="System.Exception">Hostname is already mapped.</exception>
Public Sub Add(ByVal HostName As String,
ByVal IP As String,
Optional ByVal Comment As String = Nothing)
If Not Me.FileExists() Then ' Hosts file does not exists.
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
ElseIf Not Me.ValidateIP(IP) Then ' Invalid IP address.
Throw New FormatException(String.Format("Address: '{0}' is not a valid IP adress.", IP))
ElseIf Me.IsMapped(HostName) Then ' Hostname is already mapped.
Throw New Exception(String.Format("Hostname '{0}' is already mapped.", HostName))
Else ' Add the entry.
' Fix value spacing.
Dim EntryFormat As String =
IP & HostName.Insert(0I, ControlChars.Tab) &
If(Not String.IsNullOrEmpty(Comment),
Comment.Insert(0I, ControlChars.Tab & "#"c),
String.Empty)
' Write the mapping.
File.
AppendAllText(Me._HOSTSLocation, Environment.
NewLine & EntryFormat,
Me._HOSTSEncoding
)
End If
End Sub
''' <summary>
''' Adds a new mapping.
''' </summary>
''' <param name="MappingInfo">A <see cref="MappingInfo"/> instance containing the mapping info.</param>
Public Sub Add(ByVal MappingInfo As MappingInfo)
Me.Add(MappingInfo.HostName, MappingInfo.IP, MappingInfo.Comment)
End Sub
''' <summary>
''' Disables an existing mapping.
''' </summary>
''' <param name="HostName">Indicates the Hostname.</param>
''' <exception cref="System.IO.FileNotFoundException">"Hosts file not found."</exception>
''' <exception cref="System.Exception">Hostname is not mapped.</exception>
''' <exception cref="System.Exception">Hostname is already disabled.</exception>
Public Sub Disable(ByVal HostName As String)
If Not Me.FileExists() Then ' Hosts file does not exists.
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
ElseIf Not Me.IsMapped(HostName) Then ' Hostname is not mapped.
Throw New Exception(String.Format("Hostname: '{0}' is not mapped.", HostName))
ElseIf Me.IsDisabled(HostName) Then ' Hostname is already disabled.
Throw New Exception(String.Format("Hostname: '{0}' is already disabled.", HostName))
Else ' Disable the mapping.
' Retrieve the HOSTS file content.
Dim Hosts
As List
(Of String) = File.
ReadAllLines(Me._HOSTSLocation,
Me._HOSTSEncoding
).
ToList
' Iterate the mappings.
For X As Integer = 0I To (Hosts.Count - 1I)
If Not String.IsNullOrEmpty(Hosts(X)) AndAlso Hosts(X).Contains(ControlChars.Tab) Then
' Retrieve the HostName of this mapping.
Dim Host As String = Hosts(X).Split({ControlChars.Tab})(1I)
If Host.Equals(HostName, StringComparison.OrdinalIgnoreCase) Then
' Disable the mapping.
Hosts(X) = Hosts(X).Insert(0I, "#"c)
Exit For
End If ' Host.Equals(...)
End If ' Not String.IsNullOrEmpty(Hosts(X))...
Next X
File.
WriteAllLines(Me._HOSTSLocation, Hosts,
Me._HOSTSEncoding
)
End If
End Sub
''' <summary>
''' Disables an existing mapping.
''' </summary>
''' <param name="MappingInfo">A <see cref="MappingInfo"/> instance containing the mapping info.</param>
Public Sub Disable(ByVal MappingInfo As MappingInfo)
Me.Disable(MappingInfo.HostName)
End Sub
''' <summary>
''' Removes a mapping.
''' </summary>
''' <param name="HostName">Indicates the Hostname.</param>
''' <exception cref="System.IO.FileNotFoundException">"Hosts file not found."</exception>
''' <exception cref="System.Exception">Hostname is not mapped.</exception>
Public Sub Remove(ByVal HostName As String)
If Not Me.FileExists() Then ' Hosts file does not exists.
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
ElseIf Not Me.IsMapped(HostName) Then ' Hostname is not mapped.
Throw New Exception(String.Format("Hostname: '{0}' is not mapped.", HostName))
Else ' Remove the mapping.
' Retrieve the HOSTS file content.
Dim Hosts
As List
(Of String) = File.
ReadAllLines(Me._HOSTSLocation,
Me._HOSTSEncoding
).
ToList
' Iterate the mappings.
For X As Integer = 0I To (Hosts.Count - 1I)
If Not String.IsNullOrEmpty(Hosts(X)) AndAlso Hosts(X).Contains(ControlChars.Tab) Then
' Retrieve the HostName of this mapping.
Dim Host As String = Hosts(X).Split({ControlChars.Tab})(1I)
If Host.Equals(HostName, StringComparison.OrdinalIgnoreCase) Then
' Remove the mapping.
Hosts.RemoveAt(X)
Exit For
End If ' Host.Equals(...)
End If ' Not String.IsNullOrEmpty(Hosts(X))...
Next X
File.
WriteAllLines(Me._HOSTSLocation, Hosts,
Me._HOSTSEncoding
)
End If
End Sub
''' <summary>
''' Removes a mapping.
''' </summary>
''' <param name="MappingInfo">A <see cref="MappingInfo"/> instance containing the mapping info.</param>
Public Sub Remove(ByVal MappingInfo As MappingInfo)
Me.Remove(MappingInfo.HostName)
End Sub
''' <summary>
''' Gets a <see cref="List(Of HostsMapping)"/> instance containing the mapping info of all mappings.
''' </summary>
''' <exception cref="System.IO.FileNotFoundException">"Hosts file not found."</exception>
Public Function GetMappings() As List(Of MappingInfo)
If Not Me.FileExists() Then ' Hosts file does not exists.
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
Else ' Get the mapping.
' Retrieve the HOSTS file content.
Dim Hosts
As List
(Of String) = File.
ReadAllLines(Me._HOSTSLocation,
Me._HOSTSEncoding
).
ToList Dim Mappings As New List(Of MappingInfo)
' Iterate the mappings.
For X As Integer = 0I To (Hosts.Count - 1I)
If Not String.IsNullOrEmpty(Hosts(X)) AndAlso Hosts(X).Contains(ControlChars.Tab) Then
' Retrieve the mapping parts.
Dim Parts As String() = Hosts(X).Split({ControlChars.Tab})
Dim MappingInfo As New MappingInfo
With MappingInfo
.HostName = Parts(1I)
.IP = Parts(0I).Replace("#"c, String.Empty)
.Comment = If(Parts.Count > 1I, Parts(2I), String.Empty)
.IsDisabled = Parts(0I).TrimStart.StartsWith("#"c)
End With ' MappingInfo
Mappings.Add(MappingInfo)
End If ' Not String.IsNullOrEmpty(Hosts(X))...
Next X
Return Mappings
End If
End Function
''' <summary>
''' Gets a <see cref="MappingInfo"/> instance containing the mapping info of a Hostname.
''' </summary>
''' <param name="HostName">Indicates the Hostname.</param>
''' <exception cref="System.IO.FileNotFoundException">"Hosts file not found."</exception>
''' <exception cref="System.Exception">Hostname is not mapped.</exception>
Public Function GetMappingFromHostname(ByVal Hostname As String) As MappingInfo
If Not Me.FileExists() Then ' Hosts file does not exists.
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
ElseIf Not Me.IsMapped(Hostname) Then ' Hostname is not mapped.
Throw New Exception(String.Format("Hostname: '{0}' is not mapped.", Hostname))
Else ' Get the mapping.
' Retrieve the HOSTS file content.
Dim Hosts
As List
(Of String) = File.
ReadAllLines(Me._HOSTSLocation,
Me._HOSTSEncoding
).
ToList Dim MappingInfo As New MappingInfo
' Iterate the mappings.
For X As Integer = 0I To (Hosts.Count - 1I)
If Not String.IsNullOrEmpty(Hosts(X)) AndAlso Hosts(X).Contains(ControlChars.Tab) Then
' Retrieve the mapping parts.
Dim Parts As String() = Hosts(X).Split({ControlChars.Tab})
If Parts(1I).Equals(Hostname, StringComparison.OrdinalIgnoreCase) Then
With MappingInfo
.HostName = Parts(1I)
.IP = Parts(0I).Replace("#"c, String.Empty)
.Comment = If(Parts.Count > 1I, Parts(2I), String.Empty)
.IsDisabled = Parts(0I).TrimStart.StartsWith("#"c)
End With ' MappingInfo
Exit For
End If ' Parts(1I).Equals(Hostname)...
End If ' Not String.IsNullOrEmpty(Hosts(X))...
Next X
Return MappingInfo
End If
End Function
''' <summary>
''' Gets a <see cref="List(Of HostsMapping)"/> instance containing the mapping info of all mappings
''' matching the specified IP address.
''' </summary>
''' <exception cref="System.IO.FileNotFoundException">"Hosts file not found."</exception>
''' <exception cref="System.FormatException">Invalid IP adress.</exception>
Public Function GetMappingsFromIP(ByVal IP As String) As List(Of MappingInfo)
If Not Me.FileExists() Then ' Hosts file does not exists.
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
ElseIf Not Me.ValidateIP(IP) Then ' Invalid IP address.
Throw New FormatException(String.Format("Address: '{0}' is not a valid IP adress.", IP))
Else ' Get the mapping.
' Retrieve the HOSTS file content.
Dim Hosts
As List
(Of String) = File.
ReadAllLines(Me._HOSTSLocation,
Me._HOSTSEncoding
).
ToList Dim Mappings As New List(Of MappingInfo)
' Iterate the mappings.
For X As Integer = 0I To (Hosts.Count - 1I)
If Not String.IsNullOrEmpty(Hosts(X)) AndAlso Hosts(X).Contains(ControlChars.Tab) Then
' Retrieve the mapping parts.
Dim Parts As String() = Hosts(X).Split({ControlChars.Tab})
If Parts(0I).Replace("#"c, String.Empty).Equals(IP) Then
Dim MappingInfo As New MappingInfo
With MappingInfo
.HostName = Parts(1I)
.IP = Parts(0I).Replace("#"c, String.Empty)
.Comment = If(Parts.Count > 1I, Parts(2I), String.Empty)
.IsDisabled = Parts(0I).TrimStart.StartsWith("#"c)
End With ' MappingInfo
Mappings.Add(MappingInfo)
End If
End If ' Not String.IsNullOrEmpty(Hosts(X))...
Next X
Return Mappings
End If
End Function
''' <summary>
''' Checks whether a HostName is already mapped.
''' </summary>
''' <param name="HostName">Indicates the Hostname.</param>
''' <returns><c>true</c> if the specified Hostname is mapped; otherwise, <c>false</c>.</returns>
''' <exception cref="System.IO.FileNotFoundException">"Hosts file not found."</exception>
Public Function IsMapped(ByVal HostName As String) As Boolean
If Not Me.FileExists() Then ' Hosts file does not exists.
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
Else
' Retrieve the HOSTS file content.
Dim Hosts
As List
(Of String) = File.
ReadAllLines(Me._HOSTSLocation,
Me._HOSTSEncoding
).
ToList
' Iterate the mappings.
For X As Integer = 0I To (Hosts.Count - 1I)
If Not String.IsNullOrEmpty(Hosts(X)) AndAlso Hosts(X).Contains(ControlChars.Tab) Then
' Retrieve the HostName of this mapping.
Dim Host As String = Hosts(X).Split({ControlChars.Tab})(1I)
If Host.Equals(HostName, StringComparison.OrdinalIgnoreCase) Then
Return True
End If ' Host.Equals(HostName)...
End If ' Not String.IsNullOrEmpty(Hosts(X)) AndAlso...
Next X
Return False
End If ' Not Me.Exists()...
End Function
''' <summary>
''' Checks whether a HostName is already mapped.
''' </summary>
''' <param name="MappingInfo">A <see cref="MappingInfo"/> instance containing the mapping info.</param>
''' <returns><c>true</c> if the specified Hostname is mapped; otherwise, <c>false</c>.</returns>
Public Function IsMapped(ByVal MappingInfo As MappingInfo) As Boolean
Return Me.IsMapped(MappingInfo.HostName)
End Function
''' <summary>
''' Checks whether a HostName is already disabled.
''' </summary>
''' <param name="HostName">Indicates the Hostname.</param>
''' <returns><c>true</c> if the specified Hostname is disabled; otherwise, <c>false</c>.</returns>
''' <exception cref="System.IO.FileNotFoundException">"Hosts file not found."</exception>
''' <exception cref="System.Exception">Hostname is not mapped.</exception>
Public Function IsDisabled(ByVal HostName As String) As Boolean
If Not Me.FileExists() Then ' Hosts file does not exists.
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
ElseIf Not Me.IsMapped(HostName) Then ' Hostname is not mapped.
Throw New Exception(String.Format("Hostname: '{0}' is not mapped.", HostName))
Else
' Retrieve the HOSTS file content.
Dim Hosts
As List
(Of String) = File.
ReadAllLines(Me._HOSTSLocation,
Me._HOSTSEncoding
).
ToList Dim Result As Boolean = False
' Iterate the mappings.
For X As Integer = 0I To (Hosts.Count - 1I)
If Not String.IsNullOrEmpty(Hosts(X)) AndAlso Hosts(X).Contains(ControlChars.Tab) Then
' Retrieve the HostName of this mapping.
Dim Host As String = Hosts(X).Split({ControlChars.Tab})(1I)
If Host.Equals(HostName, StringComparison.OrdinalIgnoreCase) Then
Result = Hosts(X).TrimStart.StartsWith("#"c)
Exit For
End If ' Host.Equals(HostName)...
End If ' Not String.IsNullOrEmpty(Hosts(X)) AndAlso...
Next X
Return Result
End If
End Function
''' <summary>
''' Checks whether a HostName is already disabled.
''' </summary>
''' <param name="MappingInfo">A <see cref="MappingInfo"/> instance containing the mapping info.</param>
''' <returns><c>true</c> if the specified Hostname is disabled; otherwise, <c>false</c>.</returns>
Public Function IsDisabled(ByVal MappingInfo As MappingInfo) As Boolean
Return Me.IsDisabled(MappingInfo.HostName)
End Function
''' <summary>
''' Checks whether the Hosts file exists.
''' </summary>
''' <returns><c>true</c> if Hosts file exists, <c>false</c> otherwise.</returns>
Public Function FileExists() As Boolean
Return File.
Exists(Me._HOSTSLocation
)
End Function
''' <summary>
''' Creates the Hosts file.
''' </summary>
Public Sub FileCreate()
If Me.FileExists() Then
File.
Delete(Me._HOSTSLocation
) End If
File.
WriteAllText(Me._HOSTSLocation,
Me.
HostsHeader,
Me._HOSTSEncoding
)
End Sub
''' <summary>
''' Deletes the Hosts file.
''' </summary>
''' <exception cref="System.IO.FileNotFoundException">Hosts file not found.</exception>
Public Sub FileDelete()
If Not Me.FileExists() Then
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
Else
File.
Delete(Me._HOSTSLocation
)
End If
End Sub
''' <summary>
''' Cleans the Hosts file.
''' This removes all the mappings and adds the default file header.
''' </summary>
Public Sub FileClean()
Me.FileCreate()
End Sub
''' <summary>
''' Opens the Hosts file with the specified process.
''' </summary>
''' <param name="Process">
''' Indicates the process location.
''' Default value is: "notepad.exe".
''' </param>
''' <exception cref="System.IO.FileNotFoundException">Hosts file not found.</exception>
''' <exception cref="System.IO.FileNotFoundException">Process not found.</exception>
Public Sub FileOpen(Optional ByVal Process As String = "notepad.exe")
If Not Me.FileExists Then
Throw New FileNotFoundException("Hosts file not found.", Me._HOSTSLocation)
ElseIf Not File.
Exists(Process
) Then Throw New FileNotFoundException("Process not found.", Process)
Else
Diagnostics.Process.Start(Process, ControlChars.Quote & Me._HOSTSLocation & ControlChars.Quote)
End If
End Sub
#End Region
#Region " Private Methods "
''' <summary>
''' Validates an IP address.
''' </summary>
''' <param name="Address">The IP address.</param>
''' <returns><c>true</c> if IP is in the proper format, <c>false</c> otherwise.</returns>
Private Function ValidateIP(ByVal Address As String) As Boolean
Dim IP As IPAddress = Nothing
Return IPAddress.TryParse(Address, IP)
End Function
#End Region
End Class
#End Region