HostsFileManagement.psm1
#Generated at 07/22/2019 08:59:41 by Stephane van Gulick Enum HostsEntryType{ Entry Comment BlankLine } Class HostsFile { [string]$Path [String]$ComputerName Hidden [HostsEntry[]]$Entries Hidden [int]$LogRotation = 4 ## Default Constructor HostsFile(){ $This.Path ="\\$ENV:Computername\admin$\System32\drivers\etc\hosts" $This.ComputerName = $ENV:Computername } ## Constructor that accepts a string (preferrably a computer name) HostsFile([String]$ComputerName){ If ( Test-Connection -ComputerName $ComputerName -Quiet -Count 2 ) { $This.Path = "\\$Computername\admin$\System32\drivers\etc\hosts" $This.ComputerName = $Computername } Else { Throw "Could not reach the computer $($ComputerName)" } } ## Constructor that accept a path as a file HostsFile([System.IO.FileSystemInfo]$Path){ $This.Path = $Path.FullName } ## Method to read the content of the hosts file [void]ReadHostsFileContent(){ ## Local variables $Array = New-Object System.Collections.ArrayList #@() $HostsData = Get-Content $This.Path -Encoding Ascii ## Loop through the content of the file Foreach ( $Line in $HostsData ) { $Array +=[HostsEntry]::New($Line) } ## If Array exists If ( $array ){ $This.Entries = $Array } } ## Method to get file entries [array]GetEntries(){ ## Return entries If ( $This.Entries ) { return $This.Entries } Else { Throw "No entries present. Load a Hosts file first using the 'ReadHostsFileContent()' method, or use the add() method to add entries to the Hosts file that seems to be empty." } } ## Method to add Entries [void]AddHostsEntry([HostsEntry[]]$Entries){ ## Local Variables $Added = $False [int]$Count = 0 ## Loop through Entries Foreach ( $Entry in $Entries ) { ## If current entry is not already present is the file, add it If ( ($This.entries.ipaddress.IPAddressToString -notcontains $Entry.Ipaddress.IPAddressToString) ) { $Added = $True $Count++ $This.entries += $Entry } Else { Write-Warning "The IpAddress $($Entry.ipaddress.IPAddressToString) is already present in the Hosts file." } } ## Write Verbose If ( $Added ) { Write-Verbose "Added: $($Count) entries to $($This.path). Call Set() to write to file." } } ## Method to Set LogRotation Value [Void]SetLogRotation([Int]$value){ If ( $value -in 1..100 ) { $This.LogRotation = $value } Else { Throw "LogRotation must a int between 1 and 100 ..." } } ## Method to remove Entries in the Hosts File [void]RemoveHostsEntry([HostsEntry[]]$Entries){ ## Easier to work with an arraylist $ArrayListofThisEntries = New-Object -TypeName System.Collections.ArrayList ## Fill ArrayListofThisEntries with current entries of the [HostsFile] Write-Verbose "Creating an arraylist of this.entries ... easier to work with ..." Foreach ( $CurrEntry in $This.Entries ) { $ArrayListofThisEntries.add($CurrEntry) | Out-Null } ## Remove entries passed to the method from the arraylist Foreach ( $Entry in $Entries ) { Write-Verbose "Removing the current entry: $($Entry.IpAddress) ..." $ArrayListofThisEntries.Remove($Entry) } ## Push ArrayListofThisEntries This.Entries Write-Verbose "Pushing updated arraylist to this.entries ..." $This.Entries = $ArrayListofThisEntries ## Call Set Method, will backup current Write-Verbose "Applying changes by calling this.set ..." $This.Set() } ## Backup Method [void]Backup([System.IO.DirectoryInfo]$BackupFolder){ ## Get All Hosts.bak files in the BackupFolder path $BackupItems = Get-ChildItem -Path $BackupFolder.FullName -Filter "*$($This.ComputerName)_Hosts.bak" | Sort-Object -Property CreationTime ## Check if the number of correspoing backup files is equal or greater than LogRotation Property If ( $BackupItems.Count -ge $This.LogRotation ) { #Remove the oldest Backup file Write-Verbose "LogRotation set to maximum $($This.LogRotation+1) backups. Deleting oldest backup $($BackupItems[0].Name)" $BackupItems[0].Delete() } ## Building backup file FullPath $FileStamp = Get-Date -Format 'yyyyMMdd-HHmmss' $Leaf = $FileStamp + "_" + $This.ComputerName + "_Hosts.bak" $BackupFullPath = Join-Path -Path $BackupFolder.FullName -ChildPath $Leaf ## Copying the backup file to the destination path Try { Copy-Item -Path $This.Path -Destination $BackupFullPath -ErrorAction stop Write-Verbose "Hosts file backup -> $($BackupFullPath)" } Catch { Write-Warning "$_" } } ## Backup Method [void]Backup(){ ## Get All Hosts.bak files in the default Path $BackupItems = Get-ChildItem -Path (split-Path -Path $This.Path -Parent) -Filter "*Hosts.bak" | Sort-Object CreationTime ## Check if the number of correspoing backup files is equal or greater than LogRotation Property If ($BackupItems.count -gt $This.logRotation){ ## Remove the oldest Backup file Write-Verbose "LogRotation set to maximum $($This.LogRotation+1) backups. Deleting oldest backup $($BackupItems[0].Name)" $BackupItems[0].Delete() } ## Building backup file FullPath $FileStamp = Get-Date -Format 'yyyyMMdd-HHmmss' $BackupPath = Split-Path -Parent $This.Path $Leaf = $FileStamp + "_" + "Hosts.bak" $BackupFullPath = Join-Path -Path $backupPath -ChildPath $Leaf ## Copying the backup file to the destination path Try { Copy-Item -Path $This.Path -Destination $BackupFullPath -ErrorAction stop Write-Verbose "Hosts file backup -> $($BackupFullPath)" } Catch { Write-Warning "$_" } } <# [void]Set(){ if($This.Entries){ $This.Backup() #write-warning "Waiting 3 seconds" #Start-Sleep -Seconds 3 #Set-Content -Value "" -Path $This.Path -Encoding Ascii ("") | >> $This.Path -Encoding Ascii #$This.AddHostsEntry($This.Entries) foreach ($entry in $This.Entries){ [string]$FullLine = "" #start-sleep -Seconds 1 switch($entry.EntryType){ "Comment"{ if (![string]::IsNullOrWhiteSpace($entry.Ipaddress.IPAddressToString)){ $FullLine += $entry.Ipaddress.IPAddressToString } if (![string]::IsNullOrWhiteSpace($entry.HostName)){ $FullLine += "`t`t" + $entry.hostname } if (![string]::IsNullOrWhiteSpace($entry.FullQuallifiedName)){ $FullLine += "`t`t" + $entry.FullQuallifiedName } if (![string]::IsNullOrWhiteSpace($entry.Description)){ if ($entry.Ipaddress.IpAddressToString){ $FullLine += "`t`t" + "#" + $entry.Description }else{ if ($fullLine -match '^#.+'){ $fullLine += "`t`t" + $entry.Description }else{ $FullLine += $entry.Description } } } $fullLine = "#" + $FullLine ;Break} "BlankLine"{ if ($entry.IsComment -eq $true){ $fullLine = "#" }else{ #$fullLine = "`r`n" $fullLine = "" } ;Break} "Entry"{ if (![string]::IsNullOrWhiteSpace($entry.Ipaddress.IPAddressToString)){ $FullLine += $entry.Ipaddress.IPAddressToString } if (![string]::IsNullOrWhiteSpace($entry.HostName)){ $FullLine += "`t`t" + $entry.hostname } if (![string]::IsNullOrWhiteSpace($entry.FullQuallifiedName)){ $FullLine += "`t`t" + $entry.FullQuallifiedName } if (![string]::IsNullOrWhiteSpace($entry.Description)){ $fullLine += "`t`t" + "# "+ $entry.Description } ;Break}#End Switch Entry } #$fullLine += "`r`n" try{ write-verbose "Adding: $($fullLine) to $($This.path)" Start-Sleep -Milliseconds 70 ($fullLine) | >> $This.Path -ErrorAction stop }catch{ write-warning "$_" } }#endforeach }else{ write-warning "No entries to set." } } #> ## Method to save the hosts file with changes [void]Set(){ If ( $This.Entries ) { ## Create Backup $This.Backup() #write-warning "Waiting 3 seconds" #Start-Sleep -Seconds 3 #Set-Content -Value "" -Path $This.Path -Encoding Ascii $stream = [System.IO.StreamWriter]::new($This.Path,$false) #("") | Set-Content -Path $This.Path -Encoding Ascii #$This.AddHostsEntry($This.Entries) Foreach ( $Entry in $This.Entries){ [string]$FullLine = "" #start-sleep -Seconds 1 switch($Entry.EntryType){ "Comment"{ if (![string]::IsNullOrWhiteSpace($Entry.Ipaddress.IPAddressToString)){ $FullLine += $Entry.Ipaddress.IPAddressToString } if (![string]::IsNullOrWhiteSpace($Entry.HostName)){ $FullLine += "`t`t" + $Entry.hostname } if (![string]::IsNullOrWhiteSpace($Entry.FullQuallifiedName)){ $FullLine += "`t`t" + $Entry.FullQuallifiedName } if (![string]::IsNullOrWhiteSpace($Entry.Description)){ if ($Entry.Ipaddress.IpAddressToString){ $FullLine += "`t`t" + "#" + $Entry.Description }else{ if ($fullLine -match '^#.+'){ $fullLine += "`t`t" + $Entry.Description }else{ $FullLine += $Entry.Description } } } $fullLine = "#" + $FullLine ;Break} "BlankLine"{ if ($Entry.IsComment -eq $true){ $fullLine = "#" }else{ #$fullLine = "`r`n" $fullLine = "" } ;Break} "Entry"{ if (![string]::IsNullOrWhiteSpace($Entry.Ipaddress.IPAddressToString)){ $FullLine += $Entry.Ipaddress.IPAddressToString } if (![string]::IsNullOrWhiteSpace($Entry.HostName)){ $FullLine += "`t`t" + $Entry.hostname } if (![string]::IsNullOrWhiteSpace($Entry.FullQuallifiedName)){ $FullLine += "`t`t" + $Entry.FullQuallifiedName } if (![string]::IsNullOrWhiteSpace($Entry.Description)){ $fullLine += "`t`t" + "# "+ $Entry.Description } ;Break}#End Switch Entry } #$fullLine += "`r`n" try{ write-verbose "Adding: $($fullLine) to $($This.path)" #Start-Sleep -Milliseconds 70 $stream.WriteLine($FullLine) #$fullLine | Add-Content -Path $This.Path -ErrorAction stop }catch{ write-warning "$_" } }#endforeach $stream.close() }else{ write-warning "No entries to set." } } } Class HostsEntry{ [Ipaddress]$Ipaddress [string]$HostName [String]$FullQuallifiedName [String]$Description [HostsEntryType]$EntryType HostsEntry([IpAddress]$IpAddress,[String]$HostName,[String]$FQDN,[String]$Description,[HostsEntryType]$Type){ if ($Type -eq [HostsEntryType]::BlankLine){ throw "This constructor cannot be used to create a blank line. Use the constructor with the empty signature HostsEntry()." } $This.Ipaddress = $IpAddress $This.HostName = $HostName $This.FullQuallifiedName = $FQDN $This.Description = $Description $This.EntryType = $Type } ## Add description to constructor HostsEntry([IpAddress]$IpAddress,[String]$HostName,[String]$FQDN,[String]$Description){ $This.Ipaddress = $IpAddress $This.HostName = $HostName $This.FullQuallifiedName = $FQDN $This.Description = $Description } ## Add description to constructor HostsEntry([String]$Comment,[HostsEntryType]$Type){ If ( ![Hostsentrytype]::Comment ) { throw "This constructor can only be used woth the [HostsEntryType]::Comment property." } $This.Description = $Comment $This.EntryType = $Type } ## Hiddent Constructor hidden HostsEntry([string]$Line){ ## Local variable $Type = [HostsEntry]::GetLineType($Line) ## Determine type, and populate properties Switch ($Type){ "Comment" { $This.EntryType = $Type $SplittedLine = [regex]::Split($line, "\s+") #$line.Split(" ") If ( $SplittedLine[0] -match '^#\d{1,3}\.' ) { $This.Ipaddress = $SplittedLine[0].replace("#","") $This.HostName = $SplittedLine[1] $This.FullQuallifiedName = $SplittedLine[2] [string]$comment = "" If ( $SplittedLine.count -gt 3 ) { $i = 3 While ( $i -ne $SplittedLine.count ) { If ( $SplittedLine[$i] -ne "" ) { $Comment += $SplittedLine[$i] + " " $i++ } Else { $i++ } } }#end if splitted line gt 3 If ( $Comment -match '^#.*' ) { $This.Description = $Comment.Replace("#","") } Else { $This.Description = $comment } } ElseIf ( $SplittedLine[0] -match '^#.*' ) { #$This.Ipaddress = [ipaddress]::None $This.HostName = [string]::Empty $This.FullQuallifiedName = [string]::Empty $This.Description = $line.Replace("#","") } ;Break} "BlankLine" { $This.EntryType = $Type $This.HostName = [string]::Empty $This.Description = [string]::Empty $This.FullQuallifiedName = [string]::Empty ;Break} "Entry" { $SplittedLine = [regex]::Split($line, "\s+") #$line.Split(" ") $This.Ipaddress = $SplittedLine[0] $This.HostName = $SplittedLine[1] $This.FullQuallifiedName = $SplittedLine[2] [string]$comment = "" If ( $SplittedLine.count -gt 3 ) { $i = 3 While ($i -ne $SplittedLine.count) { If ( $SplittedLine[$i] -ne "" ) { $Comment += $SplittedLine[$i] + " " $i++ } Else { $i++ } } If ($comment -match '^#.*' ) { $This.Description = $comment.Replace("#","") } Else { $This.Description = $comment } } ;Break} } } ## Default Constructor HostsEntry(){ $This.HostName = [String]::Empty $This.FullQuallifiedName = [String]::Empty $This.Description = [String]::Empty $This.EntryType = [HostsEntryType]::BlankLine } ## Method to get the type of each line: comment, blankline or entry [HostsEntryType] static hidden GetLineType([string]$Line){ ## local variables $Type = "" ## Switch to analyze the current $line with regex Switch -Regex ($Line) { '^#' { $Type = [HostsEntryType]::Comment;Break } '^\s*$' { $Type = [HostsEntryType]::BlankLine;Break } Default { $Type = [HostsEntryType]::Entry;Break } } return $Type } } Function Get-HFMHostsfile { <# .SYNOPSIS Get the hosts file of the desired hostname. .DESCRIPTION Get the hostfile of the desired hostname. By default the localhost hosts file is fetched. You can specify a remote computer name. .EXAMPLE PS C:\> Get-HFMHostsfile Return a [HostsFile] object representing the local hosts file. .EXAMPLE PS C:\> Get-HFMHostsfile -Name Computer1 Return a [HostsFile] object representing the hosts file of Computer1. .EXAMPLE PS C:\> "Computer1","Computer2" | Get-HFMHostsfile Return an array of [HostsFile] objects representing the hosts file of Computer1 and Computer2. .INPUTS Input String. .OUTPUTS Return [HostsFile] Object(s). .NOTES This cmdlet uses Class.HostsManagement classes, by @StephaneVG Fork hist project if you like it: https://github.com/Stephanevg/Class.HostsManagement Visit his site, and read his article a boute pratical use of PowerShell Classes: http://powershelldistrict.com/powershell-class/ #> [CmdletBinding()] Param ( [Alias("Name")] [Parameter(Mandatory=$False,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [String[]]$ComputerName ) BEGIN{} PROCESS{ If ( !$ComputerName ) { return [HostsFile]::New() } Else { Foreach ( $Computer in $ComputerName ) { Return [HostsFile]::New($Computer) } } } END{} } Function Get-HFMHostsFileContent { <# .SYNOPSIS Read the Host file content. .DESCRIPTION Read the Host file content. Take input from Get-HFMHostsFile. .EXAMPLE PS C:\> $a = Get-HFMHostsFile PS C:\> Get-HFMHostsFileContent -Path $a Use Get-HFMHostsFile to get a [HostsFile] object Use Get-HFMHostFileContent to return a [HostsEntry] object(s) .EXAMPLE PS C:\> Get-HFMHostsFile | Get-HFMHostsFileContent -ExcludeComments List HostsFile entrie, but exclude comments .INPUTS Input must be of type [HostsFile]. .OUTPUTS Return [HostsEntry] Object(s). .NOTES This cmdlet uses Class.HostsManagement classes, by @StephaneVG Fork hist project if you like it: https://github.com/Stephanevg/Class.HostsManagement Visit his site, and read his article a boute pratical use of PowerShell Classes: http://powershelldistrict.com/powershell-class/ #> [CmdletBinding()] Param ( [Parameter(Mandatory=$false,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [HostsFile[]]$Path, [Parameter(Mandatory=$False)] [Switch]$ExcludeComments = $False ) BEGIN {} PROCESS { Foreach ( $HostPath in $Path ) { $HostPath.ReadHostsFileContent() If ( $ExcludeComments ) { return $($HostPath.GetEntries() | Where-ObJect EntryType -ne "Comment") } Else { return $HostPath.GetEntries() } } } END {} } Function New-HFMHostsFileEntry { <# .SYNOPSIS Create a new Hosts File Entry. .DESCRIPTION Create a new Hosts File Entry. .EXAMPLE PS C:\> $NewEntry = New-HFMHostsFileEntry -IpAddress "20.0.0.0" -HostName "toto" -FullyQualifiedName "toto.com" -Description "ahahha" -EntryType Comment Create a new comment entry. .INPUTS Mostly Strings. .OUTPUTS A [HostsEntry] object. .NOTES This cmdlet uses Class.HostsManagement classes, by @StephaneVG Fork hist project if you like it: https://github.com/Stephanevg/Class.HostsManagement Visit his site, and read his article a boute pratical use of PowerShell Classes: http://powershelldistrict.com/powershell-class/ #> [CmdletBinding()] Param ( [Parameter(Mandatory=$False)] [String]$IpAddress, [Parameter(Mandatory=$False)] [String]$HostName, [Parameter(Mandatory=$False)] [String]$FullyQualifiedName, [Parameter(Mandatory=$False)] [String]$Description, [ValidateSet("Entry","Comment","BlankLine")] [Parameter(Mandatory=$True)] [String]$EntryType ) Switch ($EntryType) { BlankLine { return [HostsEntry]::New() } Comment { return [HostsEntry]::New($IpAddress,$HostName,$FullyQualifiedName,$Description,[HostsEntryType]::Comment) } Entry { return [HostsEntry]::New($IpAddress,$HostName,$FullyQualifiedName,$Description,[HostsEntryType]::Entry) } } } Function Remove-HFMHostsFileEntry { <# .SYNOPSIS Remove entry/entries from a Hosts File .DESCRIPTION Remove entry/entries from a Hosts File .EXAMPLE PS C:\> Get-HFMHostsFile | Remove-HFMHostsFileEntry -Entry "#5.0.0.0" Will remove any Comment line with ip 5.0.0.0 .EXAMPLE PS C:\> $a = Get-HFMHostsFile PS C:\> $b = New-HFMHostsFileEntry -IpAddress "20.0.0.0" -EntryType Entry PS C:\> Remove-HFMHostsFileEntry -Path $a -Entry $b Will remove any Entry line With IpAdress starting with 20.0.0.0 .EXAMPLE PS C:\> Get-HFMHostsFile | Remove-HFMHostsFileEntry -Entry "#5.0.0.0","20.0.0.0" Will remove any Comment line wich start with commented ipadress #5.0.0.0 or 20.0.0.0 .INPUTS You must provide a valid path of type [HostsFile] and an entry of type [HostsEntry] or a [String] representing an ipaddress or a comment. .OUTPUTS - .NOTES This cmdlet uses Class.HostsManagement classes, by @StephaneVG Fork and star his project if you like it: https://github.com/Stephanevg/Class.HostsManagement Visit his site, and read his article a boute pratical use of PowerShell Classes: http://powershelldistrict.com/powershell-class/ #> [CmdletBinding()] Param ( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [HostsFile[]]$Path, [Parameter(Mandatory=$True)] ## Accepte string ou [HostEntry] [Object[]]$Entry ) BEGIN{} PROCESS{ Foreach ( $File in $Path ) { If ( $null -eq $File.Entries ) { $File.ReadHostsFileContent() } $ToBeRemoved = @() Switch ( $Entry ) { ({ $PSItem.GetType().FullName -eq 'System.String' }) { If ( $PSItem -Match '^\s+$' ) { Throw "Entry can not be a string only made of spaces..."} $HostsEntry = [HostsEntry]::New($PSItem) ## Is Current Entry present in file.entries, add it to TobeRemoved Array $File.entries | Where-Object { ($_.Ipaddress -eq $HostsEntry.Ipaddress) -and ($_.EntryType -eq $HostsEntry.EntryType)} | %{ $ToBeRemoved+=$_ } Continue; } ({ $PSItem.GetType().FullName -eq 'HostsEntry'}) { $HostsEntry = $PSitem ## Is Current Entry present in file.entries, add it to TobeRemoved Array $File.entries | Where-Object { ($PSItem.Iaddress -eq $HostsEntry.IpAddress) -and ($PSItem.EntryType -eq $HostsEntry.EntryType)} | %{ $ToBeRemoved+=$_ } Continue; } Default { Throw "Entries must be of type System.String or HostsEntry"; Break } } ## Remove entries $File.RemoveHostsEntry($ToBeRemoved) } } END{} } Function Save-HFMHostFile{ <# .SYNOPSIS Backup Hosts File. .DESCRIPTION Backup Hosts File. By default the backup file will be stored in the system32\drivers\etc folder. You can use the BackupFolder to specify override the default behavior of the cmdlet. Hosts file backups are prefixed with a timestamp, and the name of the current computer. 20181010-185510_COMPUTER1_Hosts.Bak .EXAMPLE PS C:\> $a = Get-FHMHostsFile PS C:\> Save-HFMHostsFile -Path $a Creates a backup of your hosts file. .EXAMPLE PS C:\> Get-FHMHostsFile | Save-HFMHostFile -BackupFolder c:\temp Create a backup of your hosts file in the c:\temp folder. MaxLog .EXAMPLE PS C:\> "Computer1","Computer2" | Get-FHMHostsFile | Save-HFMHostsFile -BackupFolder c:\temp -MaxLogRotation 10 Creates a backup of the named computer hosts files, in your c:\temp folder. Each computer can have a max of 10 .bak files. .INPUTS Input must be of type [HostsFile]. .OUTPUTS File, extension .bak .NOTES Remember to run Powershell in elevated mode, if you must backup your current hosts file by using the following: Get-FHMHostsFile | Save-HFMHostFile Standard credential dont allow you to write inside the system32\drivers\etc folder. #> [CmdletBinding()] Param ( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [HostsFile[]]$Path, [Parameter(Mandatory=$False)] [System.IO.DirectoryInfo]$BackupFolder, [Parameter(Mandatory=$False)] [Int]$MaxLogRotation ) BEGIN{} PROCESS{ Foreach ( $HostPath in $Path ) { If ( $MaxLogRotation ) { $HostPath.LogRotation = $MaxLogRotation } If ( $BackupFolder ) { $HostPath.Backup($BackupFolder) } Else { $HostPath.Backup() } } } END{} } Function Set-HFMHostsFileEntry { <# .SYNOPSIS Add new entry/entries to hosts file. .DESCRIPTION Add new entry/entries to hosts file(s) .EXAMPLE PS C:\> $Host = Get-HFMHostsfile PS C:\> $Comment1 = New-HFMHostsFileEntry -IpAddress "20.0.0.0" -HostName "toto" -FullyQualifiedName "toto.com" -Description "ahahha" -EntryType Comment PS C:\> $Comment2 = New-HFMHostsFileEntry -IpAddress "21.0.0.0" -HostName "toto" -FullyQualifiedName "toto.com" -Description "ahahha" -EntryType Comment PS C:\> Set-HFMHostsFileEntry -Path $Host -Entries $Comment1,$Comment2 Create 2 new [HostsEntry], and add them to the local hosts file. A backup is automatically created. .EXAMPLE PS C:\> $Comment1 = New-HFMHostsFileEntry -IpAddress "20.0.0.0" -HostName "toto" -FullyQualifiedName "toto.com" -Description "ahahha" -EntryType Comment PS C:\> "Computer1","Computer2" | Get-HFMHostsfile | Set-HFMHostsFileEntry -Entries $Comment1 Create a new [HostsEntry], and add it to hostsfile on computer1, and computer2 .INPUTS You must provide a valid path of type [HostsFile] and an entry of type [HostsEntry] .OUTPUTS .NOTES This cmdlet uses Class.HostsManagement classes, by @StephaneVG Fork hist project if you like it: https://github.com/Stephanevg/Class.HostsManagement Visit his site, and read his article a boute pratical use of PowerShell Classes: http://powershelldistrict.com/powershell-class/ #> Param ( [Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)] [HostsFile[]]$Path, [Parameter(Mandatory=$True)] [HostsEntry[]]$Entries ) BEGIN{} PROCESS{ Foreach ( $File in $Path ) { $File.ReadHostsFileContent() $File.AddHostsEntry($Entries) $File.Set() } } END{} } |