Reading The Hosts File With PowerShell (local and remote)

Today’s blog focuses on reading the hosts file with PowerShell. Though there are many reasons that someone may modify the hosts file of a machine, it can easily get out of hand with entries scattered about your network.

Whatever the story, most of us have had reason to read or modify info in the hosts file at one point in our lives. We’re going to cover reading the hosts file with PowerShell locally as well as remotely for multiple machines. Yay!

Reading the hosts file with PowerShell

The hosts file is, simply put, a mapping of host names to corresponding IP addresses. You can go explore the how and the why of using it, but that’s outside the scope of this blog.

It’s easy enough to browse to the hosts file location and open the file manually. On modern versions of Windows, it’s stored here (you’ll need admin access to modify it):

%SystemRoot%\System32\drivers\etc\hosts

But, what about keeping tally of all the machines on your network? Do you really want to manually browse to this file on each machine? This is most definitely a rhetorical question. The correct answer is an emphatic, “No!”

So, what do we do? We use PowerShell of course! Reading the hosts file with PowerShell is a breeze.

Try PDQ Deploy

Getting the entire contents of hosts file with PowerShell

In order to do this, we are going to make use of the Get-Content cmdlet. This cmdlet will read the contents of a file.

If you only need to quickly see the entire contents of the hosts file, then this super simple one-liner should do the trick:

Get-Content $env:SystemRoot\System32\Drivers\etc\hosts

That’s simple enough and gets us the basic info that we’re looking for.

But, what if we want to only grab the actual entries instead of the entire file? Easy peasy with PowerShell.

Getting all entries from hosts file

In order to get all the entries from the hosts file, we’re going to use regular expressions to compare against every line in the hosts file.

Additionally, we will also log the output to a file. Having a log file will make it much easier to see all the results at a glance.

$LogFile = "\\MyScripts\Logs\hosts file results.csv"
$Pattern = '^(?<IP>\d{1,3}(\.\d{1,3}){3})\s+(?<Host>.+)$'
$File    = "$env:SystemDrive\Windows\System32\Drivers\etc\hosts"
$Entries = @()

(Get-Content -Path $File)  | ForEach-Object {
    
    If ($_ -match $Pattern) {
        
        $Entries += "$env:COMPUTERNAME,$($Matches.IP),$($Matches.Host)"
    
    }
}

$Entries | Tee-Object -FilePath $LogFile -Append

Voila! It’s fairly simple and it gets you clean results with only the actual entries in the hosts file (rather than the entire file contents).

Fantastic! Now, let’s move on to doing this for all the machines!

Getting entries from hosts file for multiple machines

So, we’ve got this fancy script to get our hosts file entries and log them to a file. Getting them from multiple machines is also a snap.

Here are a few different ways that you can accomplish this:

  • PDQ Deploy and PowerShell steps
  • PDQ Inventory and Remote Command
  • Remote PowerShell and Invoke-Command
  • Directly access the files on the remote computers via UNC path

 

PDQ Deploy and PowerShell steps

Here are the steps to use PDQ Deploy with these PowerShell scripts.

  1. Create a PDQ Deploy Package with a PowerShell Step that includes your script.
  2. Deploy to your targets and verify your log file.

Like magic, you can now deploy to all your targets and save your results to a log file on some UNC path. Go you!

PDQ Inventory and Remote Command

Here are the steps to use PDQ Inventory with these PowerShell scripts.

  1. Select your targets and use Remote Command.
  2. Save your PowerShell script to a file and call that file from PowerShell Remote Command.
  3. Select all targets to see combined results. Computers with no results will simply show, “Return code: 0” since they successfully ran but didn’t have any results.

Ta da! It’s that easy. It’s very quick to select some machines and then see what they have in their hosts file.

Remote PowerShell and Invoke-Command

This requires that you have previously configured remote PowerShell for your targets. Otherwise, you’ll receive errors when attempting to connect to your targets. I’ve added Test-WSMan to filter those results.

Additionally, we’ll need to change how we’re logging to file otherwise we’ll run into double-hop authentication issues. 

$LogFile   = "\\MyScripts\Logs\hosts file results.csv"
$Result    = @()
$Computers = @("FRY", "UTER", "WOLVERINE")

$MyScript = {

    $Pattern = '^(?<IP>\d{1,3}(\.\d{1,3}){3})\s+(?<Host>.+)$'
    $File    = "$env:SystemDrive\Windows\System32\Drivers\etc\hosts"

    (Get-Content -Path $File)  | ForEach-Object {
    
        If ($_ -match $Pattern) {
        
            "$env:COMPUTERNAME,$($Matches.IP),$($Matches.Host)"
    
        }
    }
}

Foreach ($Computer in $Computers) {

    If ( [bool](Test-WSMan -ComputerName $Computer -ErrorAction SilentlyContinue)  ) {

        $Result += Invoke-Command -ComputerName $Computer -ScriptBlock $MyScript

    }
} 

$Result | Tee-Object -FilePath $LogFile -Append

 

Directly read remote hosts file via UNC path

This method is simply using the direct UNC path to the hosts files. In this example, I’m assuming the system drive is C.

$LogFile   = "\\MyScripts\Logs\hosts file results.csv"
$Pattern   = '^(?<IP>\d{1,3}(\.\d{1,3}){3})\s+(?<Host>.+)$'
$Entries   = @()
$Computers = @("FRY", "UTER", "WOLVERINE") 

Foreach ($Computer in $Computers) {

    $file = "\\$Computer\c$\Windows\System32\Drivers\etc\hosts"
    (Get-Content -Path $File) | ForEach-Object {
        If ($_ -match $Pattern) {
        
            $Entries += "$computer,$($Matches.IP),$($Matches.Host)"
    
        }
    }
}

$Entries | Tee-Object -FilePath $LogFile -Append

This will probably be the fastest method to get the hosts file info.

Wrapping Up

That’s it! Now, you have a bunch of ways to tackle the task of reading all your hosts file records.

These are just examples, so you’ll likely want to modify them for your environment. One change that I can think of, for example, is importing your list of computers. In my examples, I am using a static list of computers.

In any case, have fun with it!

Happy PowerShelling!

 

Start a trial of PDQ Deploy

2 responses

  • I created the script and ran it against a target, but no file was created at the log file location on a UNC pathed server folder. $LogFile = “\\servername\Deploy\HostFileLogs\hosts file results.csv”

    • Thanks for reading! Sorry to hear that you’re running into some issues.

      Would you mind clarifying how you’re running the script against a target? What errors (if any) are you getting?

      If you’re using PDQ Deploy/Inventory, please verify that your credentials have read/write access to your $LogFile location.

      Also, this will only create the $LogFile file if there are entries in the hosts file. If there are no entries on a target that you’re testing this on, the file will not be created. As a test, you could create a dummy entry on a target and then verify whether or not the script is working.

      Good luck!

Respond to Kris Powell Cancel response

Your email address will not be published.

Your Name