Add-GCHostsFileEntry.ps1
<#
.SYNOPSIS Adds an entry to the hosts file. .DESCRIPTION Adds an entry to the bottom of the hosts file based on the supplied host IP address, name(s), and comment. If an entry that matches both the host name and IP address already exists, the change will be ignored. Type 'Get-Help Add-GCHostsFileEntry -Online' for extra information. .PARAMETER InputObject A PSCustomObject with the details of the hosts file entry. The schema of the object will be as follows: [PSCustomObject]@{ IPAddress=[IPAddress]; HostNames=[String[]]; Comment=[String]; } A single PSCustomObject or an array of PSCustomObjects can be passed in for addition to the hosts file. .PARAMETER IPAddress The IP address to assign to the host name. This can be an IPv4 or IPv6 address. .PARAMETER HostName The name of the host to assign the IP address to. This can be a fully qualified name such as server1.domain.com, or a flat name. An array of names is supported. .PARAMETER Comment Adds a comment on the same line as the IPAddress and HostName pair. There is no need to supply the '#' character. .PARAMETER LineComment Inserts a full line comment into the bottom of the hosts file. There is no need to supply the '#' character. .EXAMPLE The following example adds a host entry to the hosts file: Add-GCHostsFileEntry -IPAddress 1.2.3.4 -HostName 'server1.company.com' #> function Add-GCHostsFileEntry { [CmdletBinding(DefaultParameterSetName='HostEntry', HelpUri = 'https://github.com/grantcarthew/GCPowerShell')] [OutputType([String])] Param ( [Parameter(Mandatory=$false, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName='HostObject')] [PSCustomObject[]] $InputObject, [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$false, ParameterSetName='HostEntry')] [String] $IPAddress, [Parameter(Mandatory=$true, Position=1, ValueFromPipeline=$false, ParameterSetName='HostEntry')] [String[]] $HostName, [Parameter(Mandatory=$false, Position=2, ValueFromPipeline=$false, ParameterSetName='HostEntry')] [String] $Comment, [Parameter(Mandatory=$true, ValueFromPipeline=$false, ParameterSetName='LineComment')] [String] $LineComment ) begin { Write-Verbose -Message "Function initiated: $($MyInvocation.MyCommand)" Import-Module -Name GCTest $hostsFilePath = Join-Path -Path $env:SystemRoot -ChildPath '\System32\drivers\etc\hosts' Write-Verbose -Message "Hosts file path set to: $hostsFilePath" if (-not (Test-GCFileWrite -Path $hostsFilePath)) { Write-Error -Message "Can't write to the hosts file. Check it exists and you have write permissions." Exit } if ((Get-Content -Path $hostsFilePath -Raw) -notmatch "`r`n$") { Write-Verbose -Message "Adding CR-LF to the end of the hosts file." Add-Content -Path $hostsFilePath -Value '' -Encoding Ascii -Force } $hostsFileEntries = Get-GCHostsFileEntry $newEntries = New-Object -TypeName System.Collections.ArrayList $allHostNames = New-Object -TypeName System.Collections.ArrayList foreach ($entry in $hostsFileEntries) { foreach ($name in $entry.HostNames) { $allHostNames.Add($name.ToUpper().Trim()) | Out-Null } } function TestNewHostsIP ($NewIP) { # The following will cause an error if the IPAddress is invalid. # The error will be reported to the console. Write-Verbose -Message "Type casting IPAddress: $NewIP" [IPAddress]$NewIP | Out-Null } function TestDuplicateHostName ($NewHostName) { Write-Verbose -Message "Testing for duplicate entry: $NewHostName" $duplicate = $false foreach ($eachName in $NewHostName) { if ($eachName.ToUpper().Trim() -in $allHostNames) { $duplicate = $true break } } Write-Output -InputObject $duplicate } function QueueNewHostsEntry ($NewIp, $NewNames, $NewComment) { Write-Verbose -Message "Queuing new entry: $NewIp,$NewNames,$NewComment" $tab1 = 17 $newEntry = $NewIp.PadRight($tab1) foreach ($NewName in $NewNames) { $newEntry += " $NewName" } if ($NewComment) { $commentString = $NewComment.TrimStart('# ').Insert(0, '# ') $newEntry += " $commentString" } $newEntries.Add($newEntry) | Out-Null } } process { if ($LineComment) { Write-Verbose -Message "Inserting line comment." $commentString = $LineComment.TrimStart('#').Insert(0, '# ') $newEntries.Add($commentString) | Out-Null } elseif ($InputObject) { foreach ($obj in $InputObject) { TestNewHostsIP -NewIP $obj.IPAddress.IPAddressToString if (TestDuplicateHostName -NewHostName $obj.HostNames) { Write-Warning -Message "Host name already exists: $($obj.HostNames)" } else { QueueNewHostsEntry -NewIp $obj.IPAddress.IPAddressToString ` -NewNames $obj.HostNames ` -NewComment $obj.$Comment } } } else { TestNewHostsIP -NewIP $IPAddress if (TestDuplicateHostName -NewHostName $HostName) { Write-Warning -Message "Host name already exists: $HostName" } else { QueueNewHostsEntry -NewIp $IPAddress -NewNames $HostName -NewComment $Comment } } } end { if ($newEntries.Count -gt 0) { Add-Content -Path $hostsFilePath -Value $newEntries -Encoding Ascii -Force } else { Write-Warning -Message 'No host entries to add.' } Write-Verbose -Message "Function completed: $($MyInvocation.MyCommand)" } } |