Public/Add-specToHostsFile.ps1

function Add-specToHostsFile {
    <#
        .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-specToHostsFile -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-specToHostsFile -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-specToHostsFile
        This will add both entries to the hosts file if they do not already exist.
 
        .NOTES
        Author: owen.heaume
        Version 1.0.0 - Initial release
                1.0.1 - Slight refactor to better support unit testing (Create HostFilePath parameter)
                1.0.2 - Improved error handling, renaming of function
 
    #>


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

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

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

        [Parameter()]
        [string]$HostsFilePath = "$($Env:WinDir)\system32\Drivers\etc\hosts"
    )

    begin {
        # Load the hosts file, handle non-existent file scenario
        try {
            $hostsFile = if (Test-Path $HostsFilePath -ea stop) {
                Get-Content $HostsFilePath -ea stop
            } else {
                @()
            }
        } catch {
            Write-Error "An error occurred loading the hosts file: $_"
        }
    }

    process {
        try {
            Write-Host "Adding $DesiredIP for $Hostname to hosts file"

            # Pattern matching logic
            $escapedHostname = [Regex]::Escape($Hostname)
            $patternToMatch = if ($MatchOnHostnameOnly) {
                ".*\s+$escapedHostname.*"
            } else {
                ".*$DesiredIP\s+$escapedHostname.*"
            }

            # Check if entry exists
            if ($hostsFile -match $patternToMatch) {
                Write-Host "$DesiredIP".PadRight(20, ' ') "$Hostname - already exists"
            } else {
                if ($PSCmdlet.ShouldProcess("$DesiredIP $Hostname", 'Add to hosts file')) {
                    Add-Content -Encoding ASCII -Path $HostsFilePath -Value ("$DesiredIP".PadRight(20, ' ') + $Hostname) -ea Stop
                    Write-Host 'done'
                }
            }
        } catch {
            Write-Error "An error occurred processing '$hostname': $_"
        }
    }
}