function Add-HostsFileEntry { <# .SYNOPSIS Add Single entry to the Hosts File .PARAMETER Ip IP address for entry .PARAMETER Hostname Hostname for entry .PARAMETER Comment Optional comment for entry .PARAMETER HostsPath optional alternate path to hosts file .Notes This function does not support multiple host entrys per ip address on a single line This function will comment out an entry with the same hostname as the new entry, in case you want to rollback .EXAMPLE Add-HostsFileEntry -Ip "10.10.10.10" -Hostname "hello.world" .EXAMPLE Add-HostsFileEntry -Ip "10.10.10.10" -Hostname "hello.world" -HostsPath "C:\Temp\bork.txt" #> [CmdletBinding()] Param( [Parameter(Mandatory = $true)] [IpAddress]$Ip, [Parameter(Mandatory = $true)] [string]$Hostname, [Parameter(Mandatory = $false)] [string]$Comment = $null, [Parameter(Mandatory = $false)] [string]$HostsPath = "$env:windir\System32\Drivers\etc\hosts" ) $logLead = Get-LogLeadName if (($Hostname.split(" ")).Count -gt 1) { Write-Error "$logLead : You cannot supply more than one hostname" return } try { $hostsContent = Get-HostsFileContent -hostsPath $HostsPath } catch [System.IO.IOException], [System.IO.FileNotFoundException] { Write-Warning "$HostsPath is locked" Write-Warning "$loglead : Reinitiating after 5 seconds..." Start-Sleep -Seconds 5 $hostsContent = Get-HostsFileContent -hostsPath $HostsPath } catch { Write-Warning "Error encountered when attempting to read file." Write-Warning $_ throw } $hostsEntriesRebuilt = @() $hostsFileIsDirty = $false $foundMatchingLine = $false [Regex]$matchAndSplitPattern = '^(?[0-9.]+)\s+(?[\w.-]+)' $hostsEntry = "$Ip $Hostname" if ( [string]::IsNullOrWhitespace($Comment) -eq $false) { $hostsEntry = "$hostsEntry # $Comment" } foreach ($hostLine in $hostsContent) { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', '', Justification = 'We want to ensure the variable is not holding onto stale information')] $MATCHES = $null if ($hostLine -match $matchAndSplitPattern) { # MATCHES is an automatic variable, use it carefully https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-5.1#matches $matchedHostname = $MATCHES["HostName"] if ($Hostname -eq $matchedHostname) { Write-Warning "$logLead : A hosts entry already exists for entry: $matchedHostname, it will be commented out" $hostsEntriesRebuilt += "#" + $hostLine $hostsEntriesRebuilt += $hostsEntry $hostsFileIsDirty = $true $foundMatchingLine = $true Continue } } $hostsEntriesRebuilt += $hostLine } if ($foundMatchingLine -eq $false) { Write-Host "$logLead : Adding Hosts Entry : $($hostsEntry.ToString())" $hostsFileIsDirty = $true $hostsEntriesRebuilt += $hostsEntry } if ($hostsFileIsDirty -eq $true) { if (Test-IsCollectionNullOrEmpty -Collection $hostsEntriesRebuilt) { Write-Warning "Rebuilt file content is empty, exiting..." throw } else { try { Write-Host "$logLead : Saving Modified Hosts File to $HostsPath" Set-Content -Path $HostsPath -Value $hostsEntriesRebuilt -Force Write-Host "$logLead : Saved Modified Hosts File to $HostsPath" } catch [System.IO.IOException], [System.IO.FileNotFoundException] { Write-Warning "$loglead : $HostsPath is locked" Write-Warning "$loglead : Reinitiating after 5 seconds..." Start-Sleep -Seconds 5 Write-Host "$logLead : Attempt #2 : Saving Modified Hosts File to $HostsPath" Set-Content -Path $HostsPath -Value $hostsEntriesRebuilt -Force Write-Host "$logLead : Attempt #2 : Saved Modified Hosts File to $HostsPath" } catch { Write-Warning "Error encountered when attempting to write file." Write-Warning $_ throw } } } else { Write-Host"$logLead : No changes made to hosts file" } }