ps/Modules/Alkami.PowerShell.Common/Public/Add-HostsFileEntry.ps1

114 lines
4.4 KiB
PowerShell
Raw Permalink Normal View History

2023-05-30 22:51:22 -07:00
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 = '^(?<IP>[0-9.]+)\s+(?<HostName>[\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"
}
}