hosts file powershell

Learn how you can manage Hosts file with powershell. Add / remove entries to a local, or a remote hosts file using this module, based on powershell classes.

ok ok ok ok… That sounds a bit strange don’t you think? managing something ‘that’ old, with something as new as Powershell classes, why?

Well, the answer is actually pretty simple. Why not?!

Even if “the managing of Hosts files” is not something you are going to do anytime soon because you are not using Hosts files anymore. You might want to continue reading this article can anyways. It will give you great insights on how to build a solution based on powershell classes. So, give it a try, this could be a solution that will (at least I hope) give you ideas on how you can build your own powershell automation solution based on classes.

Download

The project is available on github here –> https://github.com/Stephanevg/Class.HostsManagement/

I invite you to fork it, and to comment / report bugs, and / or ask for feature requests.

 

Story behind the project:

Not that long ago, I needed to double check if a hosts entry had the correct IP Address. If not, it needed to be set or corrected. I google for powershell hosts file management, and I could find very easily functions / snippets on how to read hosts file entries  (Boe prox’s article here for example, or Jeff Hicks writes about it on the Sapien blog here ). Of course, the Carbon module with the Set-HostsEntry cmdlet , would have worked perfectly, but I didn’t want to push a module to all of my machines, just to set one hosts entry.

The main needs I had were the following ones:

  1. I need to be able to find a specific value in a local (or remote) hosts file.
  2. I need to be able to use the common powershell Technics used for filtering (Where-object etc…)
  3. I need to be able to replace a specific value in a local (or remote) hosts file.
  4. I need to be able to add a specific value in a local (or remote) hosts file.
  5. I need to be able to remove a specific value in a local (or remote) hosts file.
  6. I need to be able to create a backup of the hosts file.

I started to write a regular powershell module composed of several functions, and then, suddenly, I remembered this:

A while back, I made a promise to my self to push my self forward: “From now on, I will write only classes“. So, there you go -> hosts file change + promise = this module 🙂

In the end, I came up with a solution that is composed of a couple of classes and an enum. Together, they allowed me to manage a Hosts file (local or remote) using powershell, in a object oriented manner.
Your favorites powershell filtering Technics (where-object, etc..) that you know so well will work , and there is no need to do any ‘of that regex magic’ to find out if a specific entry is present in your Hosts file or not. Everything is handled for you under the covers.

A side note on regex: If you are interested in learning Regex (which I strongly recommend), I advise you to read my article on regex basics learning regex. You can find use cases here under:
-> How to parse netsh advfirewall rules using windows powershell
-> Parsing the WindowsUpdate.log using PowerShell and regex

 

I actually wrote another module, with ‘regular’ powershell functions. It allows to do the basic stuff you would expect from a Hosts Management module to do: Read a Hosts File, Add, remove and delete entries. It is available here.


But, as you will see throughout this article, working on an instance of a class, will drastically reduce the complexity of usage, and offers a more complete and compact set of functionality.

I invite you to read through the About_Class.Hostsmanagement help file (you can access it by typing  get-Help about_Class.HostsManagement). It explains in detail, with a big number of examples, how to use this module. This article though, goes in more depth on the structure of the classes. It is intended to help people to build their own modules containing class, and to convince them, to start writing their own modules with classes.

PowerShell Hosts management using classes:

If you take a look at the module, you will see the following three components in the Class.HostsManagment.psm1 file:

  1. HostsFile Class
  2. HostsFileEntry Class
  3. HostsEnteryType Enum

As mentionned before, the solution also comes with an About_Classes.HostsManagement document which contains detailed help and examples on how you should use this module to manage a hosts file using PowerShell.

Each class / Enum has it’s  own purpose.  Which I have tried to conceptualize in the mind map below.

If concepts such as objects, properties and methods are not that familiar to you, I invite you to go through one of my two series I wrote explaining the fundamental concepts of classes. Series 1 -> Here or Series 2 -> Here

 

Ask your self the right questions:

What is actually a Hosts file? Is there a pattern? 

The main question here, is: is there a pattern? No matter the subject, in almost every case, you will find one. If not, you might not know the subject well enough.  In this case, a host file is always structured in the same way, as mentioned on the microsoft web site.

Ipaddress <Blank line / tab> Host <Blank line / tab> FQDN <Blank line / tab>

The pound symbol is used to indicate that everything located after this symbol should be ignored. We can find it at the beginning of the line, which comments out the complete line. Or pretty often we can find it at the end of an entry, where it represents a description for that specific line (in most cases).

So to recap, we have a hosts file, that contains several entries. Each Hosts entry is located on one single line. Each line actually represents a entry. Some of the entries can actually be blank lines (to give the hosts some structure and to make it look pretty). Each entry respects a specific pattern, and can (or not) be commented. Optionally, some comments can be added at the end of the line to give some details about the line.

There you have it. In gray we have our classes, in purple the types that each line can be, which we will englobe through an Enum.

Still a bit confused? have a look at the mind map below. In gray you will see the classes, blue the properties, and in red the methods. (but you can ignore the red part “methods” for now).

mind map hosts management

 

 

Actually, to be completly honest, a mind map like will never be available for you to understand a classes structure. Developpers use something called UML Diagrams to document their classes.

UML Diagram:

One think that is important to have when you are trying to understand classes, is a UML diagram. The following one does not really respect all the UML conventions at 100%, but for now, this is enough to give us a global picture of what our solution contains as classes.


It is pretty simple to understand: Each square is a class. Each class has properties and methods. The properties are often separated from the methods by a dotted line (See the HostsFile class).
Each field has either a +, to show that the member is public and a “” to show that the member is private. In PowerShell 5.1, there is currently no such thing as “public” and “private” members. The only scope that we can use is “hidden. Private members are actually not really private, but simply ‘hidden’.

Keep in mind that this first diagram is a simplified version of the classes. This means that I didn’t put all the details in this UML diagram. Things such as private (hidden) fields and relation ships are missing here. A complete UML diagram can be found at the end of this article.

Using the Class.HostsManagement module

Powershell Hosts -> Loading the module:

Before we begin, I want to mention that working with modules containing classes, is a bit different then with regular modules.

Nothing really big, but some small things that needs to be known. One of them would be how we actually load a module that contains classes. Until now, a module has been always loaded using the “Import-Module” cmdlet, and it will still be the method of choice, if your module does not contain any classes.

To learn about this I’ll invite you to read the article “Using statement“of June Blender (Twitter) on the Sapien Blog here.

If your module contains a class, you must use the following syntax:

When we apply it to our Class.HostsManagement, it will be as follow:

 

Powershell Hosts management ->HostsFile Class

The hostsFile class is the main class of the solution. It designates which Hosts file we will be working with.

Let’s create an instance, an go through the properties and methods offered to us.

Heading back to our example, let’s have a look at the methods and properties that are available to us by piping an instance of [HostsFile] to Get-Member.

powershell HostsFile Class members

 

 

We can see the methods in red, the one and only property (Path) is represented in green. Also note, that we can see that our object has a typename of ‘HostsFile’, which happens to be our class name.

Properties

The class ‘HostsFile’ has only one and unique property called ‘Path‘. It represents the path where the HostsFile is located. You will see later, that this path can be either the default path of the hosts file, a hosts file located somewhere on your disk (The default Drivers\etc or an alternate folder).

powershell hosts file class properties

 

You can manually point this property to another HostsFile, if you want.

Methods

ReadHostsFileContent()

This is the first method you must to call, after the instanciation of HostsFile class. It will read the content from the Hosts file to which the property path points to, and load everything into memory. Once this method is called, you can see the entries that are loaded into memory using the method GetEntries().

 

GetEntries()

This method will read the values that are already loaded into memory using either the ReadHostsFileContent() or the Add() methods (Or a combination of them).

powershell hosts entries

If we take a closer look at the output, we can see that it is a structured object. I have highlighted the big parts with different colors. Each color represent a part of the hosts file (Ipaddress, HostName,Full Qualified Name, Description / Comment) and there is an additional property called “EntryType” which represents the type of entry that this particular entry / line is.

The line type is defined through the HostsEntryType Enum. (I’ll cover the HostsEntryType Enum a bit under). The hosts file entry itself is actually an instance of the HostsFileEntry class, which I talk about a bit further down in this article.

Note that the GetEntries() method does not return the values located in the Hosts File, but It will return the list that is available in memory. If you add, or remove entries using the AddHostsEntry() or RemoveHosts() methods, the content located in memory (which you can see using the GetEntries() method) can be different that the one still located in the real current Hosts file located on disk.

If you call GetEntries() prior to ReadHostsFileContet() you will actually face the following error message.

powershell hosts getentries

AddHostsEntry()

This method is used to add new hosts entries into memory. They will be added at the end of the existing ones, and can be persisted to file using the set() method.

Take a brief look at this screen shot:

powershell hosts add hosts entries

Make a mental note of the fact that this method requires an array of “HostsEntry” object(s). (We will come back to this a bit later).

AddHostsEntry only add entries into memory. To persist the content, call the set() method.

Adding a single entry

 

RemoveHostsEntry()

This method will remove a specific entry from memory, if it exists.

powershell hosts remove entry

 

Notice that this method requires an array of “HostsEntry” objects. (We will come back to this a bit later).

RemoveHostsEntry only removes entries that are located in memory. To persist the content, call the set() method.

Set()

This is probably the most important method of the HostsFile Class. The Set() Method will persist all the content that is located in memory – which can be viewed using GetHostsEntries() – on disk . To be more accurate, the data will be persisted into the file that is specified at the ‘Path‘ property.

Backup()

As you might have guessed, the Backup() method will allow you to create a backup of the Hosts file.

It is important to know, that the method set() automatically calls the Backup() method before it erases the Hosts file.

The backup() method is a bit ‘different’ from what we have seen until now, since we can use the method in several different ways.  Let’s have a look at definition.

powershell hosts backup members

As you can see in the screenshot above, the backup() method comes with two ways of using it (called overloads):

  1. A version that asks for no parameters and that returns void (nothing)
  2. A version that asks for a “backupFolder” of type System.IO.DirectoyInfo that also returns void.

The Backup() overload, will create a backup in whatever folder the Hosts file is currently located. (defined by the ‘Path‘ property).

The other backup method, Backup(System.IO.DirectoryInfo BackupFolder) will create a backup of the HOSTS file into the folder specified in the overload parameter.

In order to use the overloaded Backup() method, use get-Item to point to a folder where you want to create a backup, save it into memory, and add call the backup method passing it that variable as parameter.

Depending on which backup method (overload) you are calling, it will be either saved directly in Drivers\etc folder, or in a specific path that you specified. In either case, the backup file format will always respect the following convention:

The Backup File format: YYYYMMDD-HHmmss_Hosts.bak

Here under are examples of each of the backup methods.

[void]Backup()

[void]Backup(System.IO.DirectoryInfo BackupFolder)

 

Constructors:

We have three constructors:

HostsFile constructors

.ctor()

A parameterless constructor, which will point the path property to the default value at \\ComputerName\admin$\system32\drivers\etc\hosts (which is not visible on the screen shot above since).

 

.ctor(string)

This constructor expects a string which will allow us to specefiy a remote ComputerName. It will simply modify the path property to point to the correct computername  \\ComputerName\admin$\system32\drivers\etc\hosts

.ctor(System.IO.FileSystemInfo)

This constructor will allow to load a hosts file that is not located in the default path (Ideally this is to load a pre-existing backup file).

Use get-item -path <Path to your backup file>.

Powershell Hosts management ->Enum HostsEntryType

The HostsEntryType Enum is used in conjunction with the HostsEntry class. It is used to define the Hosts entry type (obviously). It contains the following values:

  • Comment
    • It defines a line that is commented out, thus that starts with “# (The pound symbol).
  • BlankLine
    • It identifies a line as being an empty.
  • Entry
    • It defines a complete, non commented, non empty line. It automatically implies that the line is composed of the following components (and in this order):
      • IpAddress
      • HostsName
      • FullQualifiedName
      • Comment

Powershell Hosts management -> HostsEntry

The HostsEntry class represents a single line from the Hostsfile. It is possible to create a new one from scratch.
When the HostsFile class read the content of a hosts file, using the ReadHostsFileContent() method, each line is actually converted to a HostsEntry under the covers.

If we have a look at the members of a HostsEntry instance we will see the following:

powershell hosts hostsentry members

 

As you can see, we have access to properties and methods, but here we have only interst in the properties, since the methods are all inherited from system.object and don’t really help to work on the Hosts file.

In this class, everything is pretty much done for you through the constructors and it’s different overloads.

Powershell HostsEntry Constructors:

If you take a look into our $Entry variable where we stored our new instance of the HostsEntry Class, we can see the following:

powershell hosts entry blankline

In the end, you can see that we have 5 properties, which are all blank, except for the EntryType, which is set to ‘BlankLine‘. Since we used the default constructor (the one without any parameters) it automatically created an empty line. In the end this entry will be represented in the Hosts file by an empty line.

Tip: Use this line to find out what the constructors are available for use:

These are the constructors  that are available to us in the HostsEntry class.

powershell hosts hostentries constructors

 

We have 4 overloads for our HostsEntry Constructor. Which we will go through each of them, with an example.

Constructor overload N°1: ([IpAddress]$IpAddress,[String]$HostsName,[String]$FQDN,[String]$Description, [HostsEntryType]$HostEntrType)

 

 

Constructor overload n°2: ([String]$HostsEntry)

 

Constructor overload n°3: ([String]$Comment,[HostsEntryType]$Type)

 

powershell hosts file entry

Notice how I called the constructor using two parameters:

  1. “My second Line”, which is of type String
  2. [HostsEntryType]::Comment Which is (obviously) of type HostsEntryType, and which allows us to specificy that this entry is of type Comment.

 

Constructor overload N°4: ([IpAddress]$IpAddress,[String]$HostsName,[String]$FQDN,[String]$Description)

 

This particular overload will allow to create an entry. The constructor should be smart enough to identify why type of entry it is, and will set the appropriate HostsEntryType.

 

powershell Hosts entry result

 

 

The full UML representation of the solution is here under:

 

class hosts uml full

 

By | 2017-09-29T15:13:31+00:00 May 14th, 2017|Classes|0 Comments

About the Author:

Stéphane is a dynamic and passionate Cloud and datacenter Microsoft MVP since. He is the founder of the Basel PowerShell user Group (BPUG), the co-founder of the French Speaking PowerShell UserGroup (FRPSUG), author, blogger, and received the community award "PowerShell Hero" from PowerShell.org. Stéphane has implemented microsoft infrastructure solutions in various countries of Europe and is currently working in Basel / Switzerland. Stéphane help his clients to reduce their global infrastructure costs by implementing Microsft infrastructure solutions by combining great products such as System Center, Windows Server, with heavy automation using Windows PowerShell. Stéphane loves languages, Belgium beer, French cheese and French Wine. If any of these topics are of your interest, don't hesitate to come and say hi.

Leave a Reply

%d bloggers like this: