Public/Add-specToHost.ps1

function Add-specToHost {
    <#
    .SYNOPSIS
    Adds a specified IP address and hostname to the system's hosts file.
 
    .DESCRIPTION
    This function allows you to add a new entry to the system's hosts file. You can specify an IP address and a hostname.
    It includes an option to check if only the hostname exists in the file, ignoring the IP address.
 
    .PARAMETER DesiredIP
    The IP address you wish to associate with the hostname.
 
    .PARAMETER Hostname
    The hostname (or domain name) you want to add to the hosts file.
 
    .PARAMETER MatchOnHostnameOnly
    This switch allows you to check if the hostname already exists in the hosts file, irrespective of the IP address.
    If this switch is enabled, the function will add the entry only if the hostname doesn't exist.
 
    .INPUTS
    Accepts pipeline input for objects with `DesiredIP` and `Hostname` properties.
 
    .OUTPUTS
    None
 
    .EXAMPLE
    Add-specToHost -DesiredIP "192.168.1.10" -Hostname "example.com"
    This command will add "192.168.1.10 example.com" to the hosts file if it does not already exist.
    If the hostname already exists, it WILL make a new addition (As long as the IP address is unique)
 
    .EXAMPLE
    Add-specToHost -DesiredIP "192.168.1.10" -Hostname "example.com" -MatchOnHostnameOnly
    This command will add "192.168.1.10 example.com" to the hosts file if the hostname does not already exist (Regardless of any IP associations.)
    If the hostname already exists, it will not make the addition.
 
    .EXAMPLE
    $hostEntries = @(
        [pscustomobject]@{ DesiredIP = "192.168.1.10"; Hostname = "example1.com" },
        [pscustomobject]@{ DesiredIP = "192.168.1.20"; Hostname = "example2.com" }
    )
    $hostEntries | Add-specToHost
    This will add both entries to the hosts file if they do not already exist.
 
    .NOTES
    Version 1.0.0 - Initial release
    Author: owen.heaume
    #>


    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
        [Parameter(
            Mandatory = $true,
            Position = 0,
            ValueFromPipelineByPropertyName = $true
        )]
        [string]$DesiredIP,

        [Parameter(
            Mandatory = $true,
            Position = 1,
            ValueFromPipelineByPropertyName = $true
        )]
        [string]$Hostname,

        [Parameter(
            Mandatory = $false,
            Position = 2
        )]
        [switch]$MatchOnHostnameOnly
    )

    begin {
        # Define the hosts file path once in the Begin block
        $hostsFilePath = "$($Env:WinDir)\system32\Drivers\etc\hosts"
        $hostsFile = Get-Content $hostsFilePath
    }

    process {
        Write-Host "About to add $DesiredIP for $Hostname to hosts file" -ForegroundColor Gray

        # Escape the hostname to handle special characters in regex
        $escapedHostname = [Regex]::Escape($Hostname)

        # Define the regex pattern based on the MatchOnHostnameOnly switch
        $patternToMatch = if ($MatchOnHostnameOnly) {
            ".*\s+$escapedHostname.*"
        } else {
            ".*$DesiredIP\s+$escapedHostname.*"
        }

        # Check if the entry exists
        if ($hostsFile -match $patternToMatch) {
            Write-Host $DesiredIP.PadRight(20, ' ') "$Hostname - not adding; already in hosts file" -ForegroundColor DarkYellow
        } else {
            # Check if we should proceed with adding the entry (using ShouldProcess for safety)
            if ($PSCmdlet.ShouldProcess("$DesiredIP $Hostname", 'Add to hosts file')) {
                Write-Host $DesiredIP.PadRight(20, ' ') "$Hostname - adding to hosts file... " -ForegroundColor Yellow -NoNewline
                # Add the new entry to the hosts file
                Add-Content -Encoding ASCII $hostsFilePath ("$DesiredIP".PadRight(20, ' ') + "$Hostname")
                Write-Host ' done'
            }
        }
    }

    end {
        Write-Host 'Pipeline processing complete.'
    }
}