Downloads:
1,257
Downloads of v 0.2.0:
1,014
Last Update:
12 Dec 2018
Package Maintainer(s):
Software Author(s):
- Badgerati
Tags:
powershell hosts powershell-core windows unix linux cross-platform environments profiles- Software Specific:
- Software Site
- Software License
- Software Docs
- Software Issues
- Package Specific:
- Package Source
- Package outdated?
- Package broken?
- Contact Maintainers
- Contact Site Admins
- Software Vendor?
- Report Abuse
- Download
PoshHosts
- 1
- 2
- 3
0.2.0 | Updated: 12 Dec 2018
- Software Specific:
- Software Site
- Software License
- Software Docs
- Software Issues
- Package Specific:
- Package Source
- Package outdated?
- Package broken?
- Contact Maintainers
- Contact Site Admins
- Software Vendor?
- Report Abuse
- Download
Downloads:
1,257
Downloads of v 0.2.0:
1,014
Maintainer(s):
Software Author(s):
- Badgerati
PoshHosts 0.2.0
Legal Disclaimer: Neither this package nor Chocolatey Software, Inc. are affiliated with or endorsed by Badgerati. The inclusion of Badgerati trademark(s), if any, upon this webpage is solely to identify Badgerati goods or services and not for commercial purposes.
- 1
- 2
- 3
All Checks are Passing
3 Passing Tests
Deployment Method: Individual Install, Upgrade, & Uninstall
To install PoshHosts, run the following command from the command line or from PowerShell:
To upgrade PoshHosts, run the following command from the command line or from PowerShell:
To uninstall PoshHosts, run the following command from the command line or from PowerShell:
Deployment Method:
This applies to both open source and commercial editions of Chocolatey.
1. Enter Your Internal Repository Url
(this should look similar to https://community.chocolatey.org/api/v2/)
2. Setup Your Environment
1. Ensure you are set for organizational deployment
Please see the organizational deployment guide
2. Get the package into your environment
Option 1: Cached Package (Unreliable, Requires Internet - Same As Community)-
Open Source or Commercial:
- Proxy Repository - Create a proxy nuget repository on Nexus, Artifactory Pro, or a proxy Chocolatey repository on ProGet. Point your upstream to https://community.chocolatey.org/api/v2/. Packages cache on first access automatically. Make sure your choco clients are using your proxy repository as a source and NOT the default community repository. See source command for more information.
- You can also just download the package and push it to a repository Download
-
Open Source
-
Download the package:
Download - Follow manual internalization instructions
-
-
Package Internalizer (C4B)
-
Run: (additional options)
choco download poshhosts --internalize --source=https://community.chocolatey.org/api/v2/
-
For package and dependencies run:
choco push --source="'INTERNAL REPO URL'"
- Automate package internalization
-
Run: (additional options)
3. Copy Your Script
choco upgrade poshhosts -y --source="'INTERNAL REPO URL'" [other options]
See options you can pass to upgrade.
See best practices for scripting.
Add this to a PowerShell script or use a Batch script with tools and in places where you are calling directly to Chocolatey. If you are integrating, keep in mind enhanced exit codes.
If you do use a PowerShell script, use the following to ensure bad exit codes are shown as failures:
choco upgrade poshhosts -y --source="'INTERNAL REPO URL'"
$exitCode = $LASTEXITCODE
Write-Verbose "Exit code was $exitCode"
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
if ($validExitCodes -contains $exitCode) {
Exit 0
}
Exit $exitCode
- name: Install poshhosts
win_chocolatey:
name: poshhosts
version: '0.2.0'
source: INTERNAL REPO URL
state: present
See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.
chocolatey_package 'poshhosts' do
action :install
source 'INTERNAL REPO URL'
version '0.2.0'
end
See docs at https://docs.chef.io/resource_chocolatey_package.html.
cChocoPackageInstaller poshhosts
{
Name = "poshhosts"
Version = "0.2.0"
Source = "INTERNAL REPO URL"
}
Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.
package { 'poshhosts':
ensure => '0.2.0',
provider => 'chocolatey',
source => 'INTERNAL REPO URL',
}
Requires Puppet Chocolatey Provider module. See docs at https://forge.puppet.com/puppetlabs/chocolatey.
4. If applicable - Chocolatey configuration/installation
See infrastructure management matrix for Chocolatey configuration elements and examples.
This package was approved by moderator gep13 on 17 Dec 2018.
PoshHosts is a Cross-Platform module that allows you to control the hosts file from the Command Line.
Installation will install the module for PowerShell, and PowerShell Core (if it is installed).
Features
- Control the hosts file from the command line
- Support for host profiles, useful for local environments
- Test entries in a hosts file by pinging them - even with specific ports
- Display a diff between two host files
- Support for environment sections in host files
- Support for RDPing onto servers via host entries
- Ability to open the hosts file from CLI (notepad on Windows, Vi on Unix)
The MIT License (MIT)
Copyright (c) [2018] [Matthew Kelly (Badgerati)]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
#
# Module manifest for module 'PoshHosts'
#
# Generated by: Matthew Kelly (Badgerati)
#
# Generated on: 18/11/2018
#
@{
# Script module or binary module file associated with this manifest.
RootModule = 'PoshHosts.psm1'
# Version number of this module.
ModuleVersion = '0.2.0'
# ID used to uniquely identify this module
GUID = 'f3aa217d-ec3d-306b-95d3-130dab0ac6af'
# Author of this module
Author = 'Matthew Kelly (Badgerati)'
# Copyright statement for this module
Copyright = 'Copyright (c) 2018 Matthew Kelly (Badgerati), licensed under the MIT License.'
# Description of the functionality provided by this module
Description = 'PoshHosts is a Cross-Platform module that allows you to control the hosts file from the Command Line'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '3.0'
# Functions to export from this Module
FunctionsToExport = @(
'Hosts'
)
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = @('powershell', 'hosts', 'powershell-core', 'windows', 'unix', 'linux', 'PSEdition_Core', 'cross-platform', 'environments', 'profiles')
# A URL to the license for this module.
LicenseUri = 'https://raw.githubusercontent.com/Badgerati/PoshHosts/master/LICENSE.txt'
# A URL to the main website for this project.
ProjectUri = 'https://github.com/Badgerati/PoshHosts'
}
}
}
<#
.SYNOPSIS
The hosts commands allows you to control the hosts file
.DESCRIPTION
The hosts commands allows you to control the hosts file, by adding/removing entries; as well enabling/disabling them.
Hosts also supports profiles, so you can have a developer hosts file in your repo and import/merge it for developers.
You can also test the entries by pinging them, either using the normal ping or by passing specific ports.
.EXAMPLE
hosts add 127.0.0.3 dev.test.local
.EXAMPLE
hosts export ./local.hosts
.EXAMPLE
hosts test *.local 80, 443
.EXAMPLE
hosts list -e dev
#>
function Hosts
{
param (
[Parameter(Position=0, Mandatory=$true)]
[ValidateSet('add', 'backup', 'browse', 'clear', 'diff', 'disable', 'enable', 'export', 'import',
'list', 'merge', 'open', 'path', 'rdp', 'remove', 'restore', 'set', 'show', 'test')]
[Alias('a')]
[string]
$Action,
[Parameter(Position=1)]
[Alias('v1')]
[string[]]
$Value1,
[Parameter(Position=2)]
[Alias('v2')]
[string[]]
$Value2,
[Parameter()]
[Alias('p')]
[string]
$HostsPath,
[Parameter()]
[Alias('e')]
[string]
$Environment,
[Parameter()]
[Alias('c')]
[pscredential]
$Credentials
)
if (@('diff', 'list', 'path', 'rdp', 'show', 'test') -inotcontains $Action) {
Test-AdminUser
}
try {
$Script:HostsFilePath = $HostsPath
Invoke-HostsAction -Action $Action -Value1 $Value1 -Value2 $Value2 -Environment $Environment -Credentials $Credentials
}
finally {
$Script:HostsFilePath = [string]::Empty
}
}
# load other functions
$root = Split-Path -Parent -Path $MyInvocation.MyCommand.Path
Get-ChildItem "$($root)\Tools.ps1" | Resolve-Path | ForEach-Object { . $_ }
# Export the Hosts function only
Export-ModuleMember -Function Hosts
function Invoke-HostsAction
{
param (
[Parameter()]
[string]
$Action,
[Parameter()]
[string[]]
$Value1,
[Parameter()]
[string[]]
$Value2,
[Parameter()]
[string]
$Environment,
[Parameter()]
[pscredential]
$Credentials
)
switch ($Action.ToLowerInvariant())
{
'add' {
Add-HostsFileEntries -IP (@($Value1) | Select-Object -First 1) -Hostnames $Value2 -Environment $Environment
}
'backup' {
New-HostsFileBackup -Path (@($Value1) | Select-Object -First 1) -Write
}
'browse' {
Open-HostsFileEntries -Values $Value1 -Protocol (@($Value2) | Select-Object -First 1) -Environment $Environment
}
'clear' {
Clear-HostsFile
}
'disable' {
Disable-HostsFileEntries -Values $Value1 -Environment $Environment
}
'diff' {
Compare-HostsFiles -Path (@($Value1) | Select-Object -First 1)
}
'enable' {
Enable-HostsFileEntries -Values $Value1 -Environment $Environment
}
'export' {
Export-HostsFile -Path (@($Value1) | Select-Object -First 1) -Values $Value2 -Environment $Environment
}
'import' {
Import-HostsFile -Path (@($Value1) | Select-Object -First 1) -Values $Value2 -Environment $Environment
}
'list' {
Get-HostsFile -Values $Value1 -Environment $Environment -State All
}
'merge' {
Merge-HostsFiles -Paths $Value1
}
'open' {
Open-HostsFile
}
'path' {
Write-Host "=> $(Get-HostsFilePath)"
}
'rdp' {
Invoke-HostsFileEntriesRdp -Values $Value1 -Environment $Environment -Credentials $Credentials
}
'remove' {
Remove-HostsFileEntries -Values $Value1 -Environment $Environment
}
'restore' {
Restore-HostsFile -Path (@($Value1) | Select-Object -First 1)
}
'set' {
Set-HostsFileEntries -IP (@($Value1) | Select-Object -First 1) -Hostnames $Value2 -Environment $Environment
}
'show' {
Get-Content -Path (Get-HostsFilePath) -Raw
}
'test' {
Test-HostsFileEntries -Values $Value1 -Ports $Value2 -Environment $Environment
}
}
}
function Open-HostsFile
{
$path = Get-HostsFilePath
Write-Host "=> Opening $($path)" -ForegroundColor Cyan
if (Test-IsUnix) {
vi $path
}
else {
notepad.exe $path
}
}
function Compare-HostsFiles
{
param (
[Parameter(Mandatory=$true)]
[string]
$Path
)
# ensure the path exists
if (!(Test-Path $Path)) {
throw "=> File not found: $($Path)"
}
# get the hosts file
$mainInfo = @{}
@(Get-HostsFileEntriesByState -HostsMap (@(ConvertFrom-HostsFile)) -State Enabled) | ForEach-Object {
if (!$mainInfo.ContainsKey($_.IP)) {
$mainInfo[$_.IP] = @()
}
$mainInfo[$_.IP] += $_.Hosts
}
# get the other hosts file
$otherInfo = @{}
@(Get-HostsFileEntriesByState -HostsMap (@(ConvertFrom-HostsFile -Path $Path)) -State Enabled) | ForEach-Object {
if (!$otherInfo.ContainsKey($_.IP)) {
$otherInfo[$_.IP] = @()
}
$otherInfo[$_.IP] += $_.Hosts
}
# what would be added?
$otherInfo.Keys | ForEach-Object {
$_key = $_
$_hosts = @()
if ($mainInfo.ContainsKey($_key)) {
$otherInfo[$_key] | ForEach-Object {
if ($mainInfo[$_key] -inotcontains $_) {
$_hosts += $_
}
}
}
else {
$_hosts = @($otherInfo[$_key])
}
if (($_hosts | Measure-Object).Count -gt 0) {
Write-Host "+ [$($_key) - $($_hosts -join ' ')]" -ForegroundColor Green
}
}
# what would be removed?
$mainInfo.Keys | ForEach-Object {
$_key = $_
$_hosts = @()
if ($otherInfo.ContainsKey($_key)) {
$mainInfo[$_key] | ForEach-Object {
if ($otherInfo[$_key] -inotcontains $_) {
$_hosts += $_
}
}
}
else {
$_hosts = @($mainInfo[$_key])
}
if (($_hosts | Measure-Object).Count -gt 0) {
Write-Host "- [$($_key) - $($_hosts -join ' ')]" -ForegroundColor Red
}
}
}
function Remove-HostsFileEntries
{
param (
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string]
$Environment
)
$info = @(ConvertFrom-HostsFile)
@(Set-DefaultValueAll -Values $Values) | ForEach-Object {
$_value = $_
$_entries = @(Get-HostsFileEntries -HostsMap $info -IP $_value -Environment $Environment -Hostname $_value -State All -Like)
if (($_entries | Measure-Object).Count -eq 0) {
Write-Host "=> Already removed: [$($_value)] {$(Resolve-HostsEnvironment -Environment $Environment)}" -ForegroundColor Cyan
}
else {
$_entries | ForEach-Object {
$_entry = $_
@(Get-HostsFileEntryHosts -Entry $_entry -Value $_value) | ForEach-Object {
$info = Remove-HostsFileEntry -HostsMap $info -IP $_entry.IP -Hostname $_ -Environment $Environment
}
}
}
}
# write back to hosts file
Out-HostsFile -HostsMap $info
}
function Enable-HostsFileEntries
{
param (
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string]
$Environment
)
$info = @(ConvertFrom-HostsFile)
@(Set-DefaultValueAll -Values $Values) | ForEach-Object {
$_value = $_
$_entries = @(Get-HostsFileEntries -HostsMap $info -IP $_value -Hostname $_value -Environment $Environment -State Disabled -Like)
if (($_entries | Measure-Object).Count -eq 0) {
Write-Host "=> Already enabled: [$($_value)] {$(Resolve-HostsEnvironment -Environment $Environment)}" -ForegroundColor Cyan
}
else {
$_entries | ForEach-Object {
$_entry = $_
@(Get-HostsFileEntryHosts -Entry $_entry -Value $_value) | ForEach-Object {
$info = Add-HostsFileEntry -HostsMap $info -IP $_entry.IP -Hostname $_ -Environment $Environment
}
}
}
}
# write back to hosts file
Out-HostsFile -HostsMap $info
}
function Disable-HostsFileEntries
{
param (
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string]
$Environment
)
$info = @(ConvertFrom-HostsFile)
@(Set-DefaultValueAll -Values $Values) | ForEach-Object {
$_value = $_
$_entries = @(Get-HostsFileEntries -HostsMap $info -IP $_value -Hostname $_value -Environment $Environment -State Enabled -Like)
if (($_entries | Measure-Object).Count -eq 0) {
Write-Host "=> Already disabled: [$($_value)] {$(Resolve-HostsEnvironment -Environment $Environment)}" -ForegroundColor Cyan
}
else {
$_entries | ForEach-Object {
$_entry = $_
@(Get-HostsFileEntryHosts -Entry $_entry -Value $_value) | ForEach-Object {
$info = Disable-HostsFileEntry -HostsMap $info -IP $_entry.IP -Hostname $_ -Environment $Environment
}
}
}
}
# write back to hosts file
Out-HostsFile -HostsMap $info
}
function Test-HostsFileEntries
{
param (
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string[]]
$Ports,
[Parameter()]
[string]
$Environment
)
# do we have any ports?
$hasPorts = (($Ports | Measure-Object).Count -gt 0)
# grab all enabled entries in the hosts file for the value passed
@(Get-HostsFile -Values $Values -Environment $Environment -State Enabled) | ForEach-Object {
$_ip = $_.IP
$_name = ($_.Hosts | Select-Object -First 1)
# either ping the host, or test a specific port
if (!$hasPorts) {
Test-HostsFileEntry -IP $_ip -Hostname $_name
}
else {
$Ports | ForEach-Object {
Test-HostsFileEntry -IP $_ip -Hostname $_name -Port $_
}
}
}
}
function Open-HostsFileEntries
{
param (
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string]
$Protocol,
[Parameter()]
[string]
$Environment
)
# set a default HTTPS protocol
if ([string]::IsNullOrWhiteSpace($Protocol)) {
$Protocol = 'https'
}
# grab all enabled entries in the hosts file for the value passed
@(Get-HostsFile -Values $Values -Environment $Environment -State Enabled) | ForEach-Object {
$_name = ($_.Hosts | Select-Object -First 1)
$_url = "$($Protocol)://$($_name)"
Write-Host "=> Opening: $($_url)" -ForegroundColor Cyan
Start-Process "$($_url)"
}
}
function Invoke-HostsFileEntriesRdp
{
param (
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string]
$Environment,
[Parameter()]
[pscredential]
$Credentials
)
# assign creds if passed
if ($null -ne $Credentials) {
$_domain = $Credentials.GetNetworkCredential().Domain
$_username = $Credentials.GetNetworkCredential().UserName
$_password = $Credentials.GetNetworkCredential().Password
if (![string]::IsNullOrWhiteSpace($_domain)) {
$_username = "$($_domain)\$($_username)"
}
}
# grab all enabled entries in the hosts file for the value passed
@(Get-HostsFile -Values $Values -Environment $Environment -State Enabled) | ForEach-Object {
$_ip = $_.IP
$_name = ($_.Hosts | Select-Object -First 1)
Write-Host "=> Remoting onto $($_name)" -ForegroundColor Cyan
# just attempt to open a connection if no credentials
if ($null -eq $Credentials) {
mstsc.exe /v:$_ip
}
# otherwise, add credentials to cmdkey temporarily, and then connect
else {
try {
cmdkey.exe /generic:$_ip /user:$_username /pass:$_password | Out-Null
mstsc.exe /v:$_ip
Start-Sleep -Seconds 4
}
finally {
cmdkey.exe /delete:$_ip | Out-Null
}
}
}
}
function Add-HostsFileEntries
{
param (
[Parameter(Mandatory=$true)]
[string]
$IP,
[Parameter(Mandatory=$true)]
[string[]]
$Hostnames,
[Parameter()]
[string]
$Environment
)
# get the hosts file
$info = @(ConvertFrom-HostsFile)
# loop through each hostname and add it
$Hostnames | ForEach-Object {
$info = Add-HostsFileEntry -HostsMap $info -IP $IP -Hostname $_ -Environment $Environment
}
# write back to hosts file
Out-HostsFile -HostsMap $info
}
function Set-HostsFileEntries
{
param (
[Parameter(Mandatory=$true)]
[string]
$IP,
[Parameter(Mandatory=$true)]
[string[]]
$Hostnames,
[Parameter()]
[string]
$Environment
)
# get the hosts file
$info = @(ConvertFrom-HostsFile)
# reset hosts for all the entries for the IP
$entries = @(Get-HostsFileEntry -HostsMap $info -Value $IP -Type IP -State Enabled)
if (($entries | Measure-Object).Count -eq 0) {
$info += (Get-HostsFileEntryObject -IP $IP -Hostnames @() -Environment $Environment -Enabled $true)
}
else {
$entries | ForEach-Object {
$_.Hosts = @()
$_.Environment = (Resolve-HostsEnvironment -Environment $Environment -Current $_.Environment)
}
}
# loop through each hostname and add it
$Hostnames | ForEach-Object {
$info = Add-HostsFileEntry -HostsMap $info -IP $IP -Hostname $_ -Environment $Environment
}
# write back to hosts file
Out-HostsFile -HostsMap $info
}
function Clear-HostsFile
{
# empty the hosts file
Out-HostsFile -Content ([string]::Empty) -Message 'Hosts file cleared'
}
function Restore-HostsFile
{
param (
[Parameter()]
[string]
$Path
)
try {
$details = Get-HostsFileBackupDetails -BackupPath $Path
if (!(Test-Path $details.Backup.Path)) {
throw "=> No $($details.Backup.Name) file found"
}
Copy-Item -Path $details.Backup.Path -Destination $details.Hosts.Path -Force | Out-Null
Write-Host "=> Restored hosts file from $($details.Backup.Name)" -ForegroundColor Green
}
catch {
Write-Host "=> Failed to restore hosts files from $($details.Backup.Name)" -ForegroundColor Red
}
}
function Merge-HostsFiles
{
param (
[Parameter(Mandatory=$true)]
[string[]]
$Paths
)
# ensure the paths exist
$Paths | ForEach-Object {
if (!(Test-Path $_)) {
throw "=> File not found: $($_)"
}
}
# get the hosts file
$info = @(ConvertFrom-HostsFile)
# loop through each merge path, parsing and importing them
$Paths | ForEach-Object {
$_path = $_
# loop through each entry in the file
@(ConvertFrom-HostsFile -Path $_path) | ForEach-Object {
$_entry = $_
# and now loop through each host, removing any occurrences from base file
$_entry.Hosts | ForEach-Object {
$_host = $_
# if the host exists in the base file against a different IP, then remove it
Get-HostsFileEntry -HostsMap $info -Value $_host -Type Hostname -State Enabled | ForEach-Object {
if ($_.IP -ine $_entry.IP) {
$_.Hosts = @($_.Hosts | Where-Object { $_ -ine $_host })
}
}
# call either add or disable on IP+host
if ($_entry.Enabled) {
$info = Add-HostsFileEntry -HostsMap $info -IP $_entry.IP -Hostname $_host -Environment $_entry.Environment
}
else {
$info = Disable-HostsFileEntry -HostsMap $info -IP $_entry.IP -Hostname $_host -Environment $_entry.Environment
}
}
}
}
# write back to hosts file
Out-HostsFile -HostsMap $info
}
function Import-HostsFile
{
param (
[Parameter(Mandatory=$true)]
[string]
$Path,
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string]
$Environment
)
# ensure the path exists
if (!(Test-Path $Path)) {
throw "=> File not found: $($Path)"
}
# store the main hosts file path
$_HostsPathTmp = $Script:HostsFilePath
# get the relevant entries
$Script:HostsFilePath = $Path
$info = Get-HostsFile -Values $Values -Environment $Environment -State All
# write back to main hosts file
$Script:HostsFilePath = $_HostsPathTmp
Out-HostsFile -HostsMap $info -Message "Hosts file imported from: $($Path)"
}
function Export-HostsFile
{
param (
[Parameter(Mandatory=$true)]
[string]
$Path,
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string]
$Environment
)
# get the relevant entries
$info = Get-HostsFile -Values $Values -Environment $Environment -State All
# write to export location
$Script:HostsFilePath = $Path
Out-HostsFile -HostsMap $info -Message "Hosts file exported to: $($Path)"
}
function Get-HostsFile
{
param (
[Parameter()]
[string[]]
$Values,
[Parameter()]
[string]
$Environment,
[Parameter()]
[ValidateSet('All', 'Disabled', 'Enabled')]
[string]
$State
)
$info = @(ConvertFrom-HostsFile)
$results = @()
# filter by environment and state
$info = @(Get-HostsFileEntriesByEnvironment -HostsMap $info -Environment $Environment)
$info = @(Get-HostsFileEntriesByState -HostsMap $info -State $State)
# filter by values
if (($Values | Measure-Object).Count -eq 0) {
$results = $info
}
else {
$Values | ForEach-Object {
@(Get-HostsFileEntries -HostsMap $info -IP $_ -Hostname $_ -State $State -Like) | ForEach-Object {
$_tmp = $_
if (($results | Where-Object { $_.Hash -eq $_tmp.Hash } | Measure-Object).Count -eq 0) {
$results += $_tmp
}
}
}
}
return ($results | Select-Object IP, Hosts, Environment, Enabled)
}
function New-HostsFileBackup
{
param (
[Parameter()]
[string]
$Path,
[switch]
$Write
)
$details = Get-HostsFileBackupDetails -BackupPath $Path
# if a backup exists, back that up temporarily
if (Test-Path $details.Backup.Path) {
Copy-Item -Path $details.Backup.Path -Destination $details.Backup.Temp -Force | Out-Null
}
# backup the hosts file
if (Test-Path $details.Hosts.Path) {
Copy-Item -Path $details.Hosts.Path -Destination $details.Backup.Path -Force | Out-Null
}
# remove tmp backup
if (Test-Path $details.Backup.Temp) {
Remove-Item -Path $details.Backup.Temp -Force | Out-Null
}
if ($Write) {
Write-Host "=> Hosts file backed up to $($details.Backup.Name)" -ForegroundColor Green
}
}
function Get-HostsFileBackupDetails
{
param (
[Parameter()]
[string]
$BackupPath
)
$path = Get-HostsFilePath
if ([string]::IsNullOrWhiteSpace($BackupPath)) {
$basepath = Split-Path -Parent -Path $path
if ([string]::IsNullOrWhiteSpace($basepath)) {
$basepath = '.'
}
$backup = Join-Path $basepath "$(Split-Path -Leaf -Path $path).bak"
}
else {
$backup = $BackupPath
}
return @{
'Hosts' = @{
'Path' = $path;
'Name' = (Split-Path -Leaf -Path $path);
};
'Backup' = @{
'Path' = $backup;
'Name' = (Split-Path -Leaf -Path $backup);
'Temp' = "$($backup).tmp";
};
}
}
function Set-DefaultValueAll
{
param (
[Parameter()]
[string[]]
$Values
)
if (($Values | Measure-Object).Count -eq 0) {
return @('*')
}
return @($Values)
}
function Test-AdminUser
{
# check the current platform, if it's unix then return true
if (Test-IsUnix) {
return
}
try {
$principal = New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())
if ($null -eq $principal) {
$admin = $false
}
else {
$admin = $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator)
}
}
catch [exception] {
Write-Host 'Error checking user administrator priviledges' -ForegroundColor Red
Write-Host $_.Exception.Message -ForegroundColor Red
$admin = $false
}
if (!$admin) {
throw 'Must be running with administrator priviledges to use the hosts command'
}
}
function Get-PSVersionTable
{
return $PSVersionTable
}
function Test-IsUnix
{
return (Get-PSVersionTable).Platform -ieq 'unix'
}
function Get-HostsFilePath
{
# custom path
if (![string]::IsNullOrWhiteSpace($Script:HostsFilePath)) {
return $Script:HostsFilePath
}
# unix
if (Test-IsUnix) {
return '/etc/hosts'
}
# windows is default
return "$($env:windir)\System32\drivers\etc\hosts"
}
function Get-HostsIPRegex
{
return "(?<ip>(\[[a-z0-9\:]+\]|((\d+\.){3}\d+)|\:\:\d+))"
}
function Get-HostsNameRegex
{
return "(?<hosts>((([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*([a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\s*)+)"
}
function ConvertFrom-HostsFile
{
param (
[Parameter()]
[string]
$Path
)
if ([string]::IsNullOrWhiteSpace($Path)) {
$Path = Get-HostsFilePath
}
$map = @()
$currentEnv = [string]::Empty
# if the path doesn't exist, just return
if (!(Test-Path $Path)) {
return $map
}
# parse the file
(Get-Content $Path) | ForEach-Object {
# check if it's an environment start tag
if ($_ -imatch "^\s*\#\s*\<--\s*(?<name>[a-z0-9\-]+)\s*$") {
$currentEnv = $Matches['name']
}
# check if it's an environment end tag
elseif ($_ -imatch "^\s*\#\s*--\>\s*$") {
$currentEnv = [string]::Empty
}
# check if it's a host entry
elseif ($_ -imatch "^\s*(?<enabled>[\#]{0,1})\s*$(Get-HostsIPRegex)\s+$(Get-HostsNameRegex)\s*$") {
$map += (Get-HostsFileEntryObject `
-IP ($Matches['ip'].Trim()) `
-Hostnames @($Matches['hosts'].Trim() -isplit '\s+') `
-Environment $currentEnv `
-Enabled ([string]::IsNullOrWhiteSpace($Matches['enabled'])))
}
}
$map = Update-HostsFileObject -HostsMap $map
return $map
}
function Get-HostsFileEntryObject
{
param (
[Parameter(Mandatory=$true)]
[string]
$IP,
[Parameter()]
[string[]]
$Hostnames,
[Parameter()]
[string]
$Environment,
[Parameter()]
[bool]
$Enabled
)
return (New-Object -TypeName psobject |
Add-Member -MemberType NoteProperty -Name IP -Value $IP -PassThru |
Add-Member -MemberType NoteProperty -Name Hosts $Hostnames -PassThru |
Add-Member -MemberType NoteProperty -Name Environment -Value (Resolve-HostsEnvironment -Environment $Environment) -PassThru |
Add-Member -MemberType NoteProperty -Name Enabled -Value $Enabled -PassThru |
Add-Member -MemberType NoteProperty -Name Hash -Value ([string]::Empty) -PassThru)
}
function Resolve-HostsEnvironment
{
param (
[Parameter()]
[string]
$Environment,
[Parameter()]
[string]
$Current
)
# default empty env to None
if ([string]::IsNullOrWhiteSpace($Environment)) {
$Environment = 'None'
}
# if no current env passed, just return the env
if ([string]::IsNullOrWhiteSpace($Current)) {
return $Environment
}
# if current env is not None, return current if env is also None
if ($Current -ine 'None' -and $Environment -ieq 'None') {
return $Current
}
return $Environment
}
function Update-HostsFileObject
{
param (
[Parameter()]
$HostsMap
)
$crypto = [System.Security.Cryptography.SHA256]::Create()
$HostsMap | ForEach-Object {
$str = "$($_.IP)|$($_.Hosts -join '|')|$($_.Environment)"
$_.Hash = [System.Convert]::ToBase64String($crypto.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($str)))
}
return $HostsMap
}
function ConvertTo-HostsFile
{
param (
[Parameter()]
$HostsMap
)
$str = [string]::Empty
$nl = [Environment]::NewLine
# if there are no entries, then it's empty
if (($HostsMap | Measure-Object).Count -eq 0) {
return $str
}
# get each of the environments
$HostsMap | Select-Object -ExpandProperty Environment | Group-Object | ForEach-Object {
$_env = $_.Name
$str += "#<-- $($_env)$($nl)"
# loop through each one, forming each entry line
$HostsMap | Where-Object { $_.Environment -ieq $_env } | ForEach-Object {
if ($null -ne $_ -and ![string]::IsNullOrWhiteSpace($_.IP) -and ($_.Hosts | Measure-Object).Count -gt 0) {
if (!$_.Enabled) {
$str += '# '
}
$str += "$($_.IP)`t$($_.Hosts -join ' ')$($nl)"
}
}
$str += "#-->$($nl)$($nl)"
}
return $str
}
function Get-HostsFileEntriesByEnvironment
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter()]
[string]
$Environment
)
if ([string]::IsNullOrWhiteSpace($Environment)) {
return $HostsMap
}
return @($HostsMap | Where-Object { $_.Environment -ieq $Environment })
}
function Get-HostsFileEntry
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter()]
[string]
$Value,
[Parameter()]
[ValidateSet('IP', 'Hostname')]
[string]
$Type,
[Parameter()]
[ValidateSet('All', 'Disabled', 'Enabled')]
[string]
$State,
[Parameter()]
[string]
$Environment
)
$HostsMap = @(Get-HostsFileEntriesByEnvironment -HostsMap $HostsMap -Environment $Environment)
switch ($Type.ToLowerInvariant())
{
'IP' {
$HostsMap = @($HostsMap | Where-Object { $_.IP -ieq $Value })
}
'Hostname' {
$HostsMap = @($HostsMap | Where-Object { $_.Hosts -icontains $Value })
}
}
return @(Get-HostsFileEntriesByState -HostsMap $HostsMap -State $State)
}
function Get-HostsFileEntryHosts
{
param (
[Parameter()]
[object]
$Entry,
[Parameter()]
[string]
$Value
)
if ($Entry.IP -ilike $Value) {
return @($Entry.Hosts)
}
$hosts = @()
$Entry.Hosts | Where-Object {
if ($_ -ilike $Value) {
$hosts += $_
}
}
return @($hosts)
}
function Get-HostsFileEntriesByState
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter()]
[ValidateSet('All', 'Disabled', 'Enabled')]
[string]
$State
)
switch ($State.ToLowerInvariant())
{
'disabled' {
$HostsMap = @($HostsMap | Where-Object { !$_.Enabled })
}
'enabled' {
$HostsMap = @($HostsMap | Where-Object { $_.Enabled })
}
}
return @($HostsMap)
}
function Test-HostnameAgainstDifferentIP
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter(Mandatory=$true)]
[string]
$IP,
[Parameter(Mandatory=$true)]
[string]
$Hostname,
[switch]
$Throw
)
$h = (Get-HostsFileEntry -HostsMap $HostsMap -Value $Hostname -Type Hostname -State Enabled | Select-Object -First 1)
$bound = ($null -ne $h -and $h.IP -ine $IP)
if ($Throw -and $bound) {
throw "=> The hostname [$($Hostname)] is bound against a different IP address: [$($h.IP)]"
}
return $bound
}
function Get-IPHostString
{
param (
[Parameter(Mandatory=$true)]
[string]
$IP,
[Parameter(Mandatory=$true)]
[string]
$Hostname,
[Parameter()]
[string]
$Environment
)
return "[$($IP) - $($Hostname)] {$(Resolve-HostsEnvironment -Environment $Environment)}"
}
function Remove-HostsFileEntry
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter(Mandatory=$true)]
[string]
$IP,
[Parameter(Mandatory=$true)]
[string]
$Hostname,
[Parameter()]
[string]
$Environment
)
# get entries
$entries = @(Get-HostsFileEntries -HostsMap $HostsMap -IP $IP -Hostname $Hostname -State All)
# skip if already removed
if (($entries | Measure-Object).Count -eq 0) {
Write-Host "=> Already removed $(Get-IPHostString $IP $Hostname $Environment)" -ForegroundColor Cyan
return $HostsMap
}
# remove hostname from that entries
$entries | ForEach-Object {
$_.Hosts = @($_.Hosts | Where-Object { $_ -ine $Hostname })
$_.Environment = (Resolve-HostsEnvironment -Environment $Environment -Current $_.Environment)
}
Write-Host "=> Removing $(Get-IPHostString $IP $Hostname $entries[0].Environment)"
return $HostsMap
}
function Disable-HostsFileEntry
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter(Mandatory=$true)]
[string]
$IP,
[Parameter(Mandatory=$true)]
[string]
$Hostname,
[Parameter()]
[string]
$Environment
)
# see if there's an enabled entry, and remove hostname from that entry
Get-HostsFileEntries -HostsMap $HostsMap -IP $IP -Hostname $Hostname -State Enabled | ForEach-Object {
$_.Hosts = @($_.Hosts | Where-Object { $_ -ine $Hostname })
}
# skip if already disabled
$entries = @(Get-HostsFileEntries -HostsMap $HostsMap -IP $IP -Hostname $Hostname -State Disabled)
if (($entries | Measure-Object).Count -gt 0) {
Write-Host "=> Already disabled $(Get-IPHostString $IP $Hostname $Environment)" -ForegroundColor Cyan
$entries | ForEach-Object {
$_.Environment = (Resolve-HostsEnvironment -Environment $Environment -Current $_.Environment)
}
return $HostsMap
}
# disable IP+Hostname
$entry = (Get-HostsFileEntry -HostsMap $HostsMap -Value $IP -Type IP -State Disabled | Select-Object -First 1)
if ($null -eq $entry) {
$entry = (Get-HostsFileEntryObject -IP $IP -Hostnames @($Hostname) -Environment $Environment -Enabled $false)
$HostsMap += $entry
}
else {
$entry.Hosts = @($entry.Hosts) + $Hostname
$entry.Environment = (Resolve-HostsEnvironment -Environment $Environment -Current $entry.Environment)
}
Write-Host "=> Disabling $(Get-IPHostString $IP $Hostname $entry.Environment)"
return $HostsMap
}
function Add-HostsFileEntry
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter(Mandatory=$true)]
[string]
$IP,
[Parameter(Mandatory=$true)]
[string]
$Hostname,
[Parameter()]
[string]
$Environment
)
# is the host being added, or enabled from previously being diabled?
$enabling = $false
# fail if the hostname or IP address are invalid
if ($IP -inotmatch "^$(Get-HostsIPRegex)$") {
throw "=> The IP address [$($IP)] is invalid"
}
if ($Hostname -inotmatch "^$(Get-HostsNameRegex)$") {
throw "=> The hostname [$($Hostname)] is invalid"
}
# fail if the hostname is found against a different IP
Test-HostnameAgainstDifferentIP -HostsMap $HostsMap -IP $IP -Hostname $Hostname -Throw | Out-Null
# see if there's a disabled entry, and remove hostname from that entry
Get-HostsFileEntries -HostsMap $HostsMap -IP $IP -Hostname $Hostname -State Disabled | ForEach-Object {
$enabling = $true
$_.Hosts = @($_.Hosts | Where-Object { $_ -ine $Hostname })
}
# skip if already added/enabled
$entries = @(Get-HostsFileEntries -HostsMap $HostsMap -IP $IP -Hostname $Hostname -State Enabled)
if (($entries | Measure-Object).Count -gt 0) {
Write-Host "=> Already $(if ($enabling) { 'enabled' } else { 'added' }) [$($IP) - $($Hostname)]" -ForegroundColor Cyan
$entries | ForEach-Object {
$_.Environment = (Resolve-HostsEnvironment -Environment $Environment -Current $_.Environment)
}
return $HostsMap
}
# add IP+Hostname
$entry = (Get-HostsFileEntry -HostsMap $HostsMap -Value $IP -Type IP -State Enabled | Select-Object -First 1)
if ($null -eq $entry) {
$entry = (Get-HostsFileEntryObject -IP $IP -Hostnames @($Hostname) -Environment $Environment -Enabled $true)
$HostsMap += $entry
}
else {
$entry.Hosts = @($entry.Hosts) + $Hostname
$entry.Environment = (Resolve-HostsEnvironment -Environment $Environment -Current $entry.Environment)
}
Write-Host "=> $(if ($enabling) { 'Enabling' } else { 'Adding' }) $(Get-IPHostString $IP $Hostname $entry.Environment)"
return $HostsMap
}
function Get-HostsFileEntries
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter()]
[string]
$IP,
[Parameter()]
[string]
$Hostname,
[Parameter()]
[string]
$Environment,
[Parameter()]
[ValidateSet('All', 'Disabled', 'Enabled')]
[string]
$State,
[switch]
$Like
)
$HostsMap = @(Get-HostsFileEntriesByEnvironment -HostsMap $HostsMap -Environment $Environment)
$HostsMap = @($HostsMap | Where-Object {
if ($Like) {
$_.IP -ilike $IP -or ($_.Hosts | Where-Object { $_ -ilike $Hostname } | Measure-Object).Count -ne 0
}
else {
$_.IP -ilike $IP -and ($_.Hosts | Where-Object { $_ -ilike $Hostname } | Measure-Object).Count -ne 0
}
})
return @(Get-HostsFileEntriesByState -HostsMap $HostsMap -State $State)
}
function Out-HostsFile
{
param (
[Parameter()]
[object[]]
$HostsMap,
[Parameter()]
[string]
$Content,
[Parameter()]
[string]
$Path,
[Parameter()]
[string]
$Message
)
# create backup of current
New-HostsFileBackup
# set an appropriate output message
if ([string]::IsNullOrWhiteSpace($Message)) {
$Message = 'Hosts file updated'
}
# write out to hosts file
try {
$hosts_path = Get-HostsFilePath
New-HostsFilePath -Path (Split-Path -Parent -Path $hosts_path)
if ([string]::IsNullOrWhiteSpace($Path)) {
if (($HostsMap | Measure-Object).Count -gt 0) {
$Content = ConvertTo-HostsFile -HostsMap $HostsMap
}
$Content | Out-File -FilePath $hosts_path -Encoding utf8 -Force -ErrorAction Stop | Out-Null
}
else {
Copy-Item -Path $Path -Destination $hosts_path -Force -ErrorAction Stop | Out-Null
}
Write-Host "=> $($Message)" -ForegroundColor Green
}
catch {
Restore-HostsFile
throw $_.Exception
}
}
function New-HostsFilePath
{
param (
[Parameter()]
[string]
$Path
)
if (!(Test-Path $Path)) {
New-Item -Path $Path -ItemType Directory -Force | Out-Null
}
}
function Test-HostsFileEntry
{
param (
[Parameter()]
[string]
$IP,
[Parameter()]
[string]
$Hostname,
[Parameter()]
[string]
$Port
)
# either ping the host, or test a specific port
if ([string]::IsNullOrWhiteSpace($Port)) {
Write-Host "=> Testing $($Hostname)>" -NoNewline
$result = Test-NetConnection -ComputerName $IP -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
}
else {
Write-Host "=> Testing $($Hostname):$($Port)>" -NoNewline
$result = Test-NetConnection -ComputerName $IP -Port $Port -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
}
# was the test successful or a failure?
if ($null -eq $result -or (!$result.PingSucceeded -and !$result.TcpTestSucceeded)) {
Write-Host "`tFailed" -ForegroundColor Red
}
else {
Write-Host "`tSuccess" -ForegroundColor Green
}
}
VERIFICATION
Verification is intended to assist the Chocolatey moderators and community
in verifying that this package's contents are trustworthy.
This embedded PowerShell module is packaged and distributed by the author.
The contents of which can be found on the releases pages at <https://github.com/Badgerati/PoshHosts/releases>.
To verify contents, either:
1. Compare the Checksum on the release notes against the Chocolatey source.
2. Download the zip from the release, run 'checksum -t sha256' on it, and compare.
function Remove-PoshHostsModule($path)
{
$path = Join-Path $path 'PoshHosts'
if (Test-Path $path)
{
Write-Host "Deleting PoshHosts module directory: $($path)"
Remove-Item -Path $path -Recurse -Force | Out-Null
if (!$?) {
throw "Failed to delete: $path"
}
}
}
# Determine which Program Files path to use
$progFiles = [string]$env:ProgramFiles
# Remove PS Module
# Set the module path
$modulePath = Join-Path $progFiles (Join-Path 'WindowsPowerShell' 'Modules')
# Delete PoshHosts module
Remove-PoshHostsModule $modulePath
# Remove PS-Core Module
$def = (Get-Command pwsh -ErrorAction SilentlyContinue).Definition
if (![string]::IsNullOrWhiteSpace($def))
{
# Set the module path
$modulePath = Join-Path $progFiles (Join-Path 'PowerShell' 'Modules')
# Delete PoshHosts module
Remove-PoshHostsModule $modulePath
}
Log in or click on link to see number of positives.
- poshhosts.0.2.0.nupkg (19ce64546c18) - ## / 61
In cases where actual malware is found, the packages are subject to removal. Software sometimes has false positives. Moderators do not necessarily validate the safety of the underlying software, only that a package retrieves software from the official distribution point and/or validate embedded software against official distribution point (where distribution rights allow redistribution).
Chocolatey Pro provides runtime protection from possible malware.
Add to Builder | Version | Downloads | Last Updated | Status |
---|---|---|---|---|
PoshHosts 0.2.0 | 1014 | Wednesday, December 12, 2018 | Approved | |
PoshHosts 0.1.0 | 243 | Saturday, December 8, 2018 | Approved |
Copyright 2018
This package has no dependencies.
Ground Rules:
- This discussion is only about PoshHosts and the PoshHosts package. If you have feedback for Chocolatey, please contact the Google Group.
- This discussion will carry over multiple versions. If you have a comment about a particular version, please note that in your comments.
- The maintainers of this Chocolatey Package will be notified about new comments that are posted to this Disqus thread, however, it is NOT a guarantee that you will get a response. If you do not hear back from the maintainers after posting a message below, please follow up by using the link on the left side of this page or follow this link to contact maintainers. If you still hear nothing back, please follow the package triage process.
- Tell us what you love about the package or PoshHosts, or tell us what needs improvement.
- Share your experiences with the package, or extra configuration or gotchas that you've found.
- If you use a url, the comment will be flagged for moderation until you've been whitelisted. Disqus moderated comments are approved on a weekly schedule if not sooner. It could take between 1-5 days for your comment to show up.