DSCResources/DSC_HostsFile/DSC_HostsFile.psm1
$modulePath = Join-Path -Path (Split-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -Parent) -ChildPath 'Modules' # Import the Networking Common Modules Import-Module -Name (Join-Path -Path $modulePath ` -ChildPath (Join-Path -Path 'NetworkingDsc.Common' ` -ChildPath 'NetworkingDsc.Common.psm1')) Import-Module -Name (Join-Path -Path $modulePath -ChildPath 'DscResource.Common') # Import Localization Strings $script:localizedData = Get-LocalizedData -DefaultUICulture 'en-US' <# .SYNOPSIS Returns the current state of a hosts file entry. .PARAMETER HostName Specifies the name of the computer that will be mapped to an IP address. .PARAMETER IPAddress Specifies the IP Address that should be mapped to the host name. .PARAMETER Ensure Specifies if the hosts file entry should be created or deleted. #> function Get-TargetResource { [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.String] $HostName, [Parameter()] [System.String] $IPAddress, [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present' ) Write-Verbose -Message ($script:localizedData.StartingGet -f $HostName) $result = Get-HostEntry -HostName $HostName if ($null -ne $result) { return @{ HostName = $result.HostName IPAddress = $result.IPAddress Ensure = 'Present' } } else { return @{ HostName = $HostName IPAddress = $null Ensure = 'Absent' } } } <# .SYNOPSIS Adds, updates or removes a hosts file entry. .PARAMETER HostName Specifies the name of the computer that will be mapped to an IP address. .PARAMETER IPAddress Specifies the IP Address that should be mapped to the host name. .PARAMETER Ensure Specifies if the hosts file entry should be created or deleted. #> function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $HostName, [Parameter()] [System.String] $IPAddress, [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present' ) $hostPath = "$env:windir\System32\drivers\etc\hosts" $currentValues = Get-TargetResource @PSBoundParameters Write-Verbose -Message ($script:localizedData.StartingSet -f $HostName) if ($Ensure -eq 'Present' -and $PSBoundParameters.ContainsKey('IPAddress') -eq $false) { New-InvalidArgumentException ` -Message $($($script:localizedData.UnableToEnsureWithoutIP) -f $Address, $AddressFamily) ` -ArgumentName 'IPAddress' } if ($currentValues.Ensure -eq 'Absent' -and $Ensure -eq 'Present') { Write-Verbose -Message ($script:localizedData.CreateNewEntry -f $HostName) Add-Content -Path $hostPath -Value "`r`n$IPAddress`t$HostName" } else { $hosts = Get-Content -Path $hostPath $replace = $hosts | Where-Object -FilterScript { [System.String]::IsNullOrEmpty($_) -eq $false -and $_.StartsWith('#') -eq $false -and $_ -like "*$HostName*" } $multiLineEntry = $false $data = $replace -split '\s+' if ($data.Length -gt 2) { $multiLineEntry = $true } if ($Ensure -eq 'Present') { Write-Verbose -Message ($script:localizedData.UpdateExistingEntry -f $HostName) if ($multiLineEntry -eq $true) { $newReplaceLine = $replace -replace $HostName, '' $hosts = $hosts -replace $replace, $newReplaceLine $hosts += "$IPAddress`t$HostName" } else { $hosts = $hosts -replace $replace, "$IPAddress`t$HostName" } } else { Write-Verbose -Message ($script:localizedData.RemoveEntry -f $HostName) if ($multiLineEntry -eq $true) { $newReplaceLine = $replace -replace $HostName, '' $hosts = $hosts -replace $replace, $newReplaceLine } else { $hosts = $hosts -replace $replace, '' } } Set-Content -Path $hostPath -Value $hosts } } <# .SYNOPSIS Tests the current state of a hosts file entry. .PARAMETER HostName Specifies the name of the computer that will be mapped to an IP address. .PARAMETER IPAddress Specifies the IP Address that should be mapped to the host name. .PARAMETER Ensure Specifies if the hosts file entry should be created or deleted. #> function Test-TargetResource { [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $HostName, [Parameter()] [System.String] $IPAddress, [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] $Ensure = 'Present' ) $currentValues = Get-TargetResource @PSBoundParameters Write-Verbose -Message ($script:localizedData.StartingTest -f $HostName) if ($Ensure -ne $currentValues.Ensure) { return $false } if ($Ensure -eq 'Present' -and $IPAddress -ne $currentValues.IPAddress) { return $false } return $true } function Get-HostEntry { param ( [Parameter(Mandatory = $true)] [System.String] $HostName ) $hostPath = "$env:windir\System32\drivers\etc\hosts" $allHosts = Get-Content -Path $hostPath | Where-Object -FilterScript { [System.String]::IsNullOrEmpty($_) -eq $false -and $_.StartsWith('#') -eq $false } foreach ($hosts in $allHosts) { $data = $hosts -split '\s+' if ($data.Length -gt 2) { # Account for host entries that have multiple entries on a single line $result = @() $array = @() for ($i = 1; $i -lt $data.Length; $i++) { <# Filter commments on the line. Example: 0.0.0.0 s.gateway.messenger.live.com # breaks Skype GH-183 becomes: 0.0.0.0 s.gateway.messenger.live.com #> if ($data[$i] -eq '#') { break } $array += $data[$i] } $result = @{ Host = $array IPAddress = $data[0] } } else { $result = @{ Host = $data[1] IPAddress = $data[0] } } if ($result.Host -eq $HostName) { return @{ HostName = $result.Host IPAddress = $result.IPAddress } } } } |