Script to update local host file on multiple computers

HI all. I have attempted to create a PowerShell script that reads from a csv file and updates the local workstation host file. The script checks the local workstation host file (old software requires this) for the entry and adds it if not present while leaving any other entries if they exist. The script seems to work for the first workstation in the file but none of the others. It doesn’t appear to be looping after the first workstation in the csv file. Thoughts? Thanks

The csv looks like this (tried adding commas and still doesnt work):

Workstation
TestWorkstation1
TestWorkstation2
TestWorkstation3
TestWorkstation4
TestWorkstation5

Code:

$ComputerNames = Import-Csv "c:\temp\test.csv"
ForEach ($Computername in $ComputerNames)
{
      $CN = ($ComputerName.Workstation | out-string).trim()
      if (Test-Connection -ComputerName $CN -Quiet -Count 2) {
            $file = "C$\Windows\System32\drivers\etc\hosts"
            if ($hostfile -imatch "10.10.10.10")
            {
            $Exists = "Entry Already exists on host " + $CN
            Add-Content -Path C:\Temp\Results.csv -Value $Exists
            }     else  {
                  $hostfile = Get-Content \\$CN\$file
                  $hostfile += "10.10.10.10`test1.com"
                  $hostfile += "10.10.10.10`test.test1.com"
                  $hostfile += "10.10.10.11`test2.com"
                  Set-Content -Path \\$CN\$file -Value $hostfile -Force
                  $Succeeded = "Host file updated on " + $CN
                  Add-Content -Path C:\Temp\Results.csv -Value $Succeeded
            }
      } else {
            $Failed = "Failed host file update on " + $CN
            Add-Content -Path C:\Temp\Results.csv -Value $Failed
        }
    }

This does not look correct to me:

$file = "C$\Windows\System32\drivers\etc\hosts"

Have you tried:

$file = "\\$CN\C$\Windows\System32\drivers\etc\hosts"

The script works fine and updates the host file on the first workstation in the spreadsheet but doesn’t continue down the list.

Where do you define the variable $hostfile? :smirk: :point_up_2:t4:

And just out of curiousity - why “-imatch” instead of “-match”? In PowerShell “-match” is by default case insensitive and you don’t even look for letters - only numbers?! :man_shrugging:t4:

There are so many issues with your code, including formatting/indenting. I hope these comments help you.

$Computerlist = Import-Csv "c:\temp\test.csv"

# you only need to set this once, not once a loop. Use single quotes for string literals
$file = 'C$\Windows\System32\drivers\etc\hosts'

# since you just want the workstation property, instead of having to create a new variable in the loop, just reference the property as part of the iterator
foreach ($Computername in $Computerlist.Workstation){
    # Store the hosts file path for convenience. This is using string formatting
    $hostfilepath = '\\{0}\{1}' -f $ComputerName, $file

    # This will capture whichever of the three messages get output
    $output = if(Test-Connection -ComputerName $ComputerName -Quiet -Count 2){
        # you have to get the content first. You were only getting the content if the content you didn't get matched 10.10.10.10
        $hostfile = Get-Content $hostfilepath

        # match uses regular expressions which makes 10.10.10.10 mean 10anycharactaer10anycharacter10anycharacter10 since the period matches any character
        # you either need to escape manually like "10\.10\.10\.10" or 
        if($hostfile -match [regex]::Escape("10.10.10.10")){
            # why would you ever add unstructured text to a csv. This should be structured csv output or use a txt/log file
            # and instead of collecting the output and writing it out in 3 different spots, we will just capture what gets output and write it once at the end
            "Entry Already exists on host $ComputerName"
        }
        else{
            # no reason to rewrite the whole file if you're just adding data. 
            # also `t in double quotes is the tab character, so are you really writing est1.com, est.test1.com, and est2.com? 
            $content = $(
                "10.10.10.10`ttest1.com"
                "10.10.10.10`ttest.test1.com"
                "10.10.10.11`ttest2.com"
            )
            Add-Content -Path $hostfilepath -Value $content -Force
            "Host file updated on $ComputerName"
        }
    }
    else {
        "Ping test failed for $ComputerName"
    }

    Add-Content -Path C:\Temp\Results.csv -Value $output
}
1 Like

Thank you for the clear explanation.