534 lines
23 KiB
PowerShell
534 lines
23 KiB
PowerShell
|
function Update-SystemPortReservations {
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Updates the system port reservations if they haven't been set yet.
|
||
|
This script is intended to automate me out of a job. This script is for developer environment setup and exceptional override
|
||
|
|
||
|
.PARAMETER AddRange
|
||
|
Supply an array of value-tuples for creating one or more ranges.
|
||
|
Value tuple is defined as an array of two integers: StartPort, NumerOfPorts
|
||
|
Example input: Update-SystemPortReservations -AddRange @(50000,30)
|
||
|
Example input: Update-SystemPortReservations -AddRange @(@(50000,30),@(12345,2))
|
||
|
|
||
|
.PARAMETER RemoveRange
|
||
|
Supply an array of value-tuples for removing one or more ranges.
|
||
|
Value tuple is defined as an array of two integers: StartPort, NumerOfPorts
|
||
|
Example input: Update-SystemPortReservations -RemoveRange @(@(50000,30),@(12345,2))
|
||
|
#>
|
||
|
[CmdletBinding()]
|
||
|
param (
|
||
|
[Parameter(Mandatory = $false)]
|
||
|
[Alias("Create")]
|
||
|
$AddRange = $null,
|
||
|
[Parameter(Mandatory = $false)]
|
||
|
[Alias("Destroy")]
|
||
|
$RemoveRange = $null
|
||
|
)
|
||
|
|
||
|
$logLead = (Get-LogLeadName)
|
||
|
$validationErrors = @()
|
||
|
$wasRunningProcessNames = @()
|
||
|
|
||
|
Write-Host "$logLead : Ensure basic system registrations have occurred - IPListens"
|
||
|
Set-DefaultNetshIPListens
|
||
|
|
||
|
Write-Host "$logLead : Ensure basic system registrations have occurred - URL ACLs"
|
||
|
Set-DefaultNetshURLACLS
|
||
|
|
||
|
#region internal-private functions to make life easier
|
||
|
function Get-EnvironmentVariableNameForRange {
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
This function is internal only and is used to consistently return the variable name
|
||
|
This function should not be a standalone function as it only applies to this specific file
|
||
|
|
||
|
.PARAMETER rangeStart
|
||
|
This parameter is the Start of the range.
|
||
|
|
||
|
.PARAMETER NumberOfPorts
|
||
|
The number of ports in the range
|
||
|
|
||
|
.PARAMETER End
|
||
|
The End port in the range
|
||
|
#>
|
||
|
[CmdletBinding(DefaultParameterSetName = 'NumberOfPorts')]
|
||
|
param (
|
||
|
[Parameter(Mandatory = $false)]
|
||
|
$Start,
|
||
|
[Parameter(Mandatory = $true, ParameterSetName = 'NumberOfPorts')]
|
||
|
[ValidateNotNullOrEmpty()]
|
||
|
[Alias("Range")]
|
||
|
[int]$NumberOfPorts,
|
||
|
[Parameter(Mandatory = $true, ParameterSetName = 'EndPorts')]
|
||
|
[ValidateNotNullOrEmpty()]
|
||
|
[Alias("EndPort")]
|
||
|
[int]$End
|
||
|
)
|
||
|
|
||
|
if ($Start -le 0) {
|
||
|
throw "$logLead : Start port value must be greater than 0"
|
||
|
}
|
||
|
|
||
|
if ($PSCmdlet.ParameterSetName -eq 'NumberOfPorts') {
|
||
|
if ($NumberOfPorts -eq $Start) {
|
||
|
throw "$logLead : NumberOfPorts can not equal the parameter for Start"
|
||
|
}
|
||
|
|
||
|
if ($NumberOfPorts -le 0) {
|
||
|
throw "$logLead : NumberOfPorts value must be greater than 0"
|
||
|
}
|
||
|
|
||
|
$End = $NumberOfPorts + $Start - 1
|
||
|
}
|
||
|
|
||
|
if ($PSCmdlet.ParameterSetName -eq 'EndPorts') {
|
||
|
if ($End -le $Start) {
|
||
|
throw "$logLead : End port value must be larger than Start port value"
|
||
|
}
|
||
|
|
||
|
if ($End -le 0) {
|
||
|
throw "$logLead : End port value must be greater than 0"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return "ALKAMI.SRE.EXCLUDED_PORT_RANGE_CONFIGURED.$Start.$End"
|
||
|
}
|
||
|
|
||
|
function Stop-AnyProcessesInPortRange {
|
||
|
<#
|
||
|
.SYNOPSIS
|
||
|
Stop any processes that are using these ports. Return the names so we can try to restart any services.
|
||
|
|
||
|
.PARAMETER Start
|
||
|
This parameter is the Start of the range.
|
||
|
|
||
|
.PARAMETER NumberOfPorts
|
||
|
The number of ports in the range
|
||
|
|
||
|
.PARAMETER End
|
||
|
The End port in the range
|
||
|
#>
|
||
|
[CmdletBinding(DefaultParameterSetName = 'NumberOfPorts')]
|
||
|
param (
|
||
|
[Parameter(Mandatory = $false)]
|
||
|
$Start,
|
||
|
[Parameter(Mandatory = $true, ParameterSetName = 'NumberOfPorts')]
|
||
|
[ValidateNotNullOrEmpty()]
|
||
|
[Alias("Range")]
|
||
|
[int]$NumberOfPorts,
|
||
|
[Parameter(Mandatory = $true, ParameterSetName = 'EndPorts')]
|
||
|
[ValidateNotNullOrEmpty()]
|
||
|
[Alias("EndPort")]
|
||
|
[int]$End
|
||
|
)
|
||
|
|
||
|
$runningProcessNames = @()
|
||
|
|
||
|
if ($Start -le 0) {
|
||
|
throw "$logLead : Start port value must be greater than 0"
|
||
|
}
|
||
|
|
||
|
if ($PSCmdlet.ParameterSetName -eq 'NumberOfPorts') {
|
||
|
if ($NumberOfPorts -eq $Start) {
|
||
|
throw "$logLead : NumberOfPorts can not equal the parameter for Start"
|
||
|
}
|
||
|
|
||
|
if ($NumberOfPorts -le 0) {
|
||
|
throw "$logLead : NumberOfPorts value must be greater than 0"
|
||
|
}
|
||
|
|
||
|
$End = $NumberOfPorts + $Start - 1
|
||
|
}
|
||
|
|
||
|
if ($PSCmdlet.ParameterSetName -eq 'EndPorts') {
|
||
|
if ($End -le $Start) {
|
||
|
throw "$logLead : End port value must be larger than Start port value"
|
||
|
}
|
||
|
|
||
|
if ($End -le 0) {
|
||
|
throw "$logLead : End port value must be greater than 0"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$allBoundProcessPorts = (Get-NetTCPConnection).LocalPort | Sort-Object -Unique
|
||
|
|
||
|
Write-Host "$logLead : Looking for ports between [$Start] and [$End]"
|
||
|
|
||
|
$runningProcessPorts = @($allBoundProcessPorts.Where({$_ -ge $Start -and $_ -le $End}))
|
||
|
|
||
|
if (Test-IsCollectionNullOrEmpty $runningProcessPorts) {
|
||
|
Write-Host "$logLead : Found no actively used ports, nothing to stop"
|
||
|
return $runningProcessNames
|
||
|
}
|
||
|
|
||
|
Write-Host "$logLead : Found [$($runningProcessPorts.Length)] actively used ports"
|
||
|
|
||
|
# We found some processes, let's kill 'em
|
||
|
foreach($processPort in $runningProcessPorts) {
|
||
|
# It's possible we already killed a process that was holding more than one port open
|
||
|
$netTcpConnection = Get-NetTCPConnection -LocalPort $processPort -ErrorAction Ignore
|
||
|
if ($null -ne $netTcpConnection) {
|
||
|
$process = Get-Process -Id ($netTcpConnection).OwningProcess -ErrorAction Ignore
|
||
|
|
||
|
if ($null -eq $process) {
|
||
|
# The process was already killed a moment ago. This is normal.
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
$processName = $process.Name
|
||
|
$processPath = $process.Path
|
||
|
|
||
|
# Test to ensure this is not the System process, and that it has a path
|
||
|
if ([string]::IsNullOrEmpty($processPath)) {
|
||
|
Write-Host "$logLead : [$processName] was running on process [$processPort] with no path. Skipping"
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
Write-Warning "$logLead : Found [$processName] running and keeping [$processPort] open. Killing this process by force."
|
||
|
Write-Host "$logLead : [$processName] was running at path [$processPath]. Will try to restart at the end if this was a service"
|
||
|
$runningProcessNames += $processName
|
||
|
|
||
|
$processId = $process.Id
|
||
|
Stop-Process -Id $processId -Force
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $runningProcessNames
|
||
|
}
|
||
|
#endregion internal-private functions to make life easier
|
||
|
|
||
|
Write-Host "$logLead : Updating system port reservations"
|
||
|
|
||
|
<#
|
||
|
Once a range is committed to this table, please do not edit it except under extreme duress
|
||
|
If you need to add "a longer port" you would want to just make a new grouping
|
||
|
Example: the "standard default" is 50000 + 30 ports (to 50029) so if we wanted instead
|
||
|
50000 + 60, what you would do here is @{ Start = 50030; NumberOfPorts = 30; }
|
||
|
Plus the other fields as indicated below.
|
||
|
|
||
|
These ranges once set are "set in stone"
|
||
|
There are machine level environment variables that get set as well
|
||
|
So if you want to remove something, you have to ensure you call that
|
||
|
#>
|
||
|
$createRanges = @(
|
||
|
@{ Start = 50000; NumberOfPorts = 30; CollidingReservations = @(); }
|
||
|
@{ Start = 12345; NumberOfPorts = 2; CollidingReservations = @(); }
|
||
|
)
|
||
|
|
||
|
# Be very careful what you do here.
|
||
|
# If you MUST delete one from the above table, move it here.
|
||
|
$destroyExistingRanges = @(
|
||
|
)
|
||
|
|
||
|
#region process the inputs
|
||
|
if (!(Test-IsCollectionNullOrEmpty $AddRange)) {
|
||
|
# $AddRange was supplied with some set of values. Let's evaluate those for validness.
|
||
|
$createRanges = @()
|
||
|
if (($AddRange.Length -eq 2) -and ($AddRange[0] -is [int])) {
|
||
|
$createRanges += @{ Start = $AddRange[0]; NumberOfPorts = $AddRange[1]; CollidingReservations = @(); }
|
||
|
} else {
|
||
|
foreach($range in $AddRange) {
|
||
|
if (($range.Length -eq 2) -and ($range[0] -is [int]) -and ($range[1] -is [int])) {
|
||
|
$createRanges += @{ Start = $range[0]; NumberOfPorts = $range[1]; CollidingReservations = @(); }
|
||
|
} else {
|
||
|
$validationErrors += "$logLead : Could not parse the input parameter for AddRange. Should be an array of two ints, or an array of arrays of int pairs."
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} elseif (!(Test-IsCollectionNullOrEmpty $RemoveRange)) {
|
||
|
# There was no create range input, but there was a remove range input
|
||
|
# Therefore we only want to remove the ranges supplied
|
||
|
$createRanges = @()
|
||
|
}
|
||
|
|
||
|
if (!(Test-IsCollectionNullOrEmpty $RemoveRange)) {
|
||
|
# $RemoveRange was supplied with some set of values. Let's evaluate those for validness.
|
||
|
$destroyExistingRanges = @()
|
||
|
if (($RemoveRange.Length -eq 2) -and ($RemoveRange[0] -is [int])) {
|
||
|
$destroyExistingRanges += @{ Start = $RemoveRange[0]; NumberOfPorts = $RemoveRange[1]; }
|
||
|
} else {
|
||
|
foreach($range in $RemoveRange) {
|
||
|
if (($range.Length -eq 2) -and ($range[0] -is [int]) -and ($range[1] -is [int])) {
|
||
|
$destroyExistingRanges += @{ Start = $range[0]; NumberOfPorts = $range[1]; }
|
||
|
} else {
|
||
|
$validationErrors += "$logLead : Could not parse the input parameter for RemoveRange. Should be an array of two ints, or an array of arrays of int pairs."
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!(Test-IsCollectionNullOrEmpty $validationErrors)) {
|
||
|
#Some errors were found. Stop now.
|
||
|
|
||
|
foreach($validationError in $validationErrors) {
|
||
|
Write-Error $validationError
|
||
|
}
|
||
|
throw "$logLead : Please resolve errors in input and try again"
|
||
|
}
|
||
|
#endregion process the inputs
|
||
|
|
||
|
#region fast abort if create-only and all ranges exist
|
||
|
# Start with true only if we have values to test, otherwise start with false
|
||
|
$allRangeMachineEnvVarsExist = !(Test-IsCollectionNullOrEmpty $createRanges)
|
||
|
|
||
|
if (Test-IsCollectionNullOrEmpty $destroyExistingRanges) {
|
||
|
foreach($range in $createRanges) {
|
||
|
if ($null -eq (Get-EnvironmentVariable -Name (Get-EnvironmentVariableNameForRange -Start $range.Start -NumberOfPorts $range.NumberOfPorts) -StoreName Machine)) {
|
||
|
# $null means the var does not exist
|
||
|
$allRangeMachineEnvVarsExist = $false
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($allRangeMachineEnvVarsExist) {
|
||
|
Write-Host "$logLead : All the requested ranges seem to exist. Nothing to do."
|
||
|
return
|
||
|
}
|
||
|
#endregion fast abort if create-only and all ranges exist
|
||
|
|
||
|
<#
|
||
|
__ __ __ ____ _ _
|
||
|
( \/ ) /__\ (_ _)( )_( )
|
||
|
) ( /(__)\ )( ) _ (
|
||
|
(_/\/\_)(__)(__)(__) (_) (_)
|
||
|
,_ . .
|
||
|
|_ ,-. | | ,-. . , , ,-.
|
||
|
| | | | | | | |/|/ `-.
|
||
|
| `-' `' `' `-' ' ' `-'
|
||
|
'
|
||
|
|
||
|
There are two locations below that use this set of calculations.
|
||
|
I included this enormous block of text so that I can keep track of the
|
||
|
Logical math taking place. There's 3 complex logic sets to monitor
|
||
|
So I want to make sure that my logic is sound
|
||
|
|
||
|
It is possible to have overlapping ranges that are problematic
|
||
|
We need to remove some conditions if they already exist
|
||
|
In some cases they may be our own cause, but hopefully we already
|
||
|
Resolved those with the removals above.
|
||
|
|
||
|
In the examples below we want to consider a $range in $createRanges
|
||
|
Range: Start 100 NumberOfPorts 100
|
||
|
DesiredRangeStart: 100 (DRS)
|
||
|
DesiredRangeEnd: 199 (DRE)
|
||
|
|
||
|
Non-conflicting conditions to handle:
|
||
|
Defined range matches our request
|
||
|
How can this happen? This script runs on a machine that has
|
||
|
already been configured before the environment variables were added
|
||
|
RangeStart: 100 (RS)
|
||
|
RangeEnd: 199 (RE)
|
||
|
RS -eq DRS -and RE -eq DRE
|
||
|
|
||
|
Action to be taken in this case:
|
||
|
Create the environment variable on this machine, continue loop
|
||
|
|
||
|
Conflicting conditions:
|
||
|
|
||
|
Conflict #1: "hangs over the beginning"
|
||
|
99 - 101 already exists as a reserved set of ports
|
||
|
RangeStart: 99 (RS)
|
||
|
RangeEnd: 101 (RE)
|
||
|
RS -lt DRS -and RE -gt DRS -and RE -lt DRE
|
||
|
99 -lt 100 -and 101 -gt 100 -and 101 -lt 199
|
||
|
|
||
|
Conflict #2: "hangs over the end"
|
||
|
198 - 201 already exists as a reserved set of ports
|
||
|
RangeStart: 198 (RS)
|
||
|
RangeEnd: 201 (RE)
|
||
|
RS -gt DRS -and RS -lt DRE -and RE -gt DRE
|
||
|
198 -gt 100 -and 198 -lt 199 -and 201 -gt 199
|
||
|
|
||
|
Conflict #3: "narrow condition"
|
||
|
140 - 160 already exists as a reserved set of ports
|
||
|
RangeStart: 140 (RS)
|
||
|
RangeEnd: 160 (RE)
|
||
|
RS -gt DRS -and RE -lt DRE
|
||
|
140 -gt 100 -and 160 -lt 199
|
||
|
|
||
|
As a visualization:
|
||
|
Desired: |--------------------|
|
||
|
Conf 1: |-----|
|
||
|
Conf 2: |-----|
|
||
|
Conf 3: |------|
|
||
|
#>
|
||
|
|
||
|
#region validate the create ranges don't overlap
|
||
|
foreach($range in $createRanges) {
|
||
|
$desiredRangeStart = $range.Start
|
||
|
$desiredRangeEnd = $range.Start + $range.NumberOfPorts - 1
|
||
|
$otherRanges = $createRanges.Where({!(($_.Start -eq $range.Start) -and ($_.NumberOfPorts -eq $range.NumberOfPorts))})
|
||
|
foreach($otherRange in $otherRanges) {
|
||
|
$rangeStart = $otherRange.Start
|
||
|
$rangeEnd = $otherRange.Start + $otherRange.NumberOfPorts - 1
|
||
|
|
||
|
# As a visualization:
|
||
|
# Desired: |--------------------|
|
||
|
# Conf 1: |-----|
|
||
|
# Conf 2: |-----|
|
||
|
# Conf 3: |------|
|
||
|
|
||
|
$conflictCondition1 = ($rangeStart -le $desiredRangeStart) -and ($rangeEnd -gt $desiredRangeStart) -and ($rangeEnd -lt $desiredRangeEnd)
|
||
|
$conflictCondition2 = ($rangeStart -gt $desiredRangeStart) -and ($rangeStart -lt $desiredRangeEnd) -and ($rangeEnd -ge $desiredRangeEnd)
|
||
|
$conflictCondition3 = ($rangeStart -gt $desiredRangeStart) -and ($rangeEnd -lt $desiredRangeEnd)
|
||
|
|
||
|
if ($conflictCondition1 -or $conflictCondition2 -or $conflictCondition3) {
|
||
|
$validationErrors += "$logLead : Range crossover exception. Create range with Start $($range.Start) and NumberOfPorts $($range.NumberOfPorts) has a range conflict with the create range with values Start $($otherRange.Start) NumberOfPorts $($otherRange.NumberOfPorts)."
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!(Test-IsCollectionNullOrEmpty $validationErrors)) {
|
||
|
#Some errors were found. Stop now.
|
||
|
|
||
|
foreach($validationError in $validationErrors) {
|
||
|
Write-Error $validationError
|
||
|
}
|
||
|
throw "$logLead : Please resolve errors in input and try again"
|
||
|
}
|
||
|
#endregion validate the ranges don't overlap
|
||
|
|
||
|
$existingRanges = @(Get-NetshExcludedPortRanges)
|
||
|
|
||
|
#region ensure the delete ranges already exist to be deleted
|
||
|
foreach($range in $destroyExistingRanges) {
|
||
|
$desiredRangeStart = $range.Start
|
||
|
$desiredRangeEnd = $range.Start + $range.NumberOfPorts - 1
|
||
|
$activeDeleteRanges = $existingRanges.Where({!(($_.Start -eq $desiredRangeStart) -and ($_.End -eq $desiredRangeEnd))})
|
||
|
if (Test-IsCollectionNullOrEmpty $activeDeleteRanges) {
|
||
|
$validationErrors += "$logLead : There are no existing ranges to remove for Start $($range.Start) NumberOfPorts $($range.NumberOfPorts) FinalPort $($desiredRangeEnd)"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!(Test-IsCollectionNullOrEmpty $validationErrors)) {
|
||
|
#Some errors were found. Stop now.
|
||
|
|
||
|
foreach($validationError in $validationErrors) {
|
||
|
Write-Error $validationError
|
||
|
}
|
||
|
throw "$logLead : Please resolve errors in input and try again"
|
||
|
}
|
||
|
#endregion ensure the delete ranges already exist to be deleted
|
||
|
|
||
|
#region destroy before creating
|
||
|
if (!(Test-IsCollectionNullOrEmpty $destroyExistingRanges)) {
|
||
|
# Destroying before you create saves you a lot of hassle
|
||
|
# It does mean reading the system state twice, but that should be ok for what we are doing
|
||
|
foreach($range in $destroyExistingRanges) {
|
||
|
$wasRunningProcessNames += @(Stop-AnyProcessesInPortRange -Start $range.Start -NumberOfPorts $range.NumberOfPorts)
|
||
|
|
||
|
Write-Host "$logLead : Ready to delete range with Start $($range.Start) NumberOfPorts $($range.NumberOfPorts)"
|
||
|
|
||
|
# The function returns a true-false value if it succeeds or fails
|
||
|
if (Remove-NetshExcludedPortRange -Start $range.Start -NumberOfPorts $range.NumberOfPorts) {
|
||
|
Remove-EnvironmentVariable -Name (Get-EnvironmentVariableNameForRange -Start $range.Start -NumberOfPorts $range.NumberOfPorts) -StoreName Machine
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Test-IsCollectionNullOrEmpty $createRanges) {
|
||
|
# If we only came here to destroy things, let's get out of here!
|
||
|
Write-Host "$logLead : All ranges destroyed, nothing to create. Done"
|
||
|
return
|
||
|
}
|
||
|
|
||
|
# Since we just nuked the ranges, let's just recreate from the system to be sure we got 'em all
|
||
|
$existingRanges = (Get-NetshExcludedPortRanges)
|
||
|
}
|
||
|
#endregion destroy before creating
|
||
|
|
||
|
#region look for existing non-reserved ranges that need to be destroyed
|
||
|
foreach($range in $createRanges) {
|
||
|
$desiredRangeStart = $range.Start
|
||
|
$desiredRangeEnd = $range.Start + $range.NumberOfPorts - 1
|
||
|
$envVarName = (Get-EnvironmentVariableNameForRange -Start $range.Start -NumberOfPorts $range.NumberOfPorts)
|
||
|
if ($null -ne (Get-EnvironmentVariable $envVarName)) {
|
||
|
Write-Verbose "$logLead : non-reserved destroy range check : Environment range already set for Start $($range.Start) NumberOfPorts $($range.NumberOfPorts), skipping"
|
||
|
continue
|
||
|
}
|
||
|
foreach($existingRange in $existingRanges) {
|
||
|
$rangeStart = $existingRange.Start
|
||
|
$rangeEnd = $existingRange.End
|
||
|
|
||
|
# As a visualization:
|
||
|
# Desired: |--------------------|
|
||
|
# Non-Conf: |--------------------|
|
||
|
# Conf 1: |-----|
|
||
|
# Conf 2: |-----|
|
||
|
# Conf 3: |------|
|
||
|
|
||
|
$nonconflictCondition = ($rangeStart -eq $desiredRangeStart) -and ($rangeEnd -eq $desiredRangeEnd)
|
||
|
|
||
|
if ($nonconflictCondition) {
|
||
|
Set-EnvironmentVariable -Name $envVarName -Value $true -StoreName Machine
|
||
|
Write-Host "$logLead : Found an already existing range for Start $($range.Start) NumberOfPorts $($range.NumberOfPorts). Setting Machine Environment Variable and continuing."
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
$conflictCondition1 = ($rangeStart -le $desiredRangeStart) -and ($rangeEnd -gt $desiredRangeStart) -and ($rangeEnd -lt $desiredRangeEnd)
|
||
|
$conflictCondition2 = ($rangeStart -gt $desiredRangeStart) -and ($rangeStart -lt $desiredRangeEnd) -and ($rangeEnd -ge $desiredRangeEnd)
|
||
|
$conflictCondition3 = ($rangeStart -gt $desiredRangeStart) -and ($rangeEnd -lt $desiredRangeEnd)
|
||
|
|
||
|
if ($conflictCondition1 -or $conflictCondition2 -or $conflictCondition3) {
|
||
|
$range.CollidingReservations += @{ Start = $rangeStart; End = $rangeEnd; }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endregion look for existing non-reserved ranges that need to be destroyed
|
||
|
|
||
|
#region remove excess regions so we can create the ones we need to create
|
||
|
$haveDeleteRanges = @($createRanges.Where({!(Test-IsCollectionNullOrEmpty $_.CollidingReservations)}))
|
||
|
if (!(Test-IsCollectionNullOrEmpty $haveDeleteRanges)) {
|
||
|
$allBoundProcessPorts = (Get-NetTCPConnection).LocalPort | Sort-Object -Unique
|
||
|
foreach($range in $haveDeleteRanges) {
|
||
|
foreach ($reservation in $range.CollidingReservations) {
|
||
|
# Remove the existing reservations
|
||
|
# There may be a port conflict because something may have the port in use.
|
||
|
# Now we get to see if ANY other application is using that port right now,
|
||
|
# And try to force-kill them
|
||
|
# We can't clear the port range until these processes are stopped.
|
||
|
# We have to repeat the process before we create each range, as well, just in case.
|
||
|
|
||
|
$wasRunningProcessNames += @(Stop-AnyProcessesInPortRange -Start $reservation.Start -End $reservation.End)
|
||
|
|
||
|
$portCount = $reservation.End - $reservation.Start + 1
|
||
|
# TODO: Add support for SupportsShouldProcess
|
||
|
Write-Host "$logLead : Removing conflicting port reservation to enable properly configuring requested range. Removing Start [$($reservation.Start)] NumberOfPorts [$($portCount)]"
|
||
|
# The function returns a true-false value if it succeeds or fails
|
||
|
if (Remove-NetshExcludedPortRange -Start $reservation.Start -NumberOfPorts $portCount) {
|
||
|
Remove-EnvironmentVariable (Get-EnvironmentVariableNameForRange -Start $reservation.Start -NumberOfPorts $portCount)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endregion remove excess regions so we can create the ones we need to create
|
||
|
|
||
|
#region now the moment we've all been waiting for
|
||
|
# all the overlapping/conflicting ranges should now be deleted
|
||
|
foreach($range in $createRanges) {
|
||
|
$envVarName = (Get-EnvironmentVariableNameForRange -Start $range.Start -NumberOfPorts $range.NumberOfPorts)
|
||
|
if ($null -ne (Get-EnvironmentVariable $envVarName)) {
|
||
|
Write-Host "$logLead : Environment range already set for Start $($range.Start) NumberOfPorts $($range.NumberOfPorts), skipping"
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
# Ensure that the ports we want to create don't have anything using them
|
||
|
# This is usually where things go hairy if at all
|
||
|
$wasRunningProcessNames += @(Stop-AnyProcessesInPortRange -Start $range.Start -NumberOfPorts $range.NumberOfPorts)
|
||
|
|
||
|
# The function returns a true-false value if it succeeds or fails
|
||
|
if (Add-NetshExcludedPortRange -Start $range.Start -NumberOfPorts $range.NumberOfPorts) {
|
||
|
Write-Host "$logLead : Created excluded port range with Start $($range.Start) NumberOfPorts $($range.NumberOfPorts)"
|
||
|
Set-EnvironmentVariable -Name $envVarName -Value $true -StoreName Machine
|
||
|
}
|
||
|
}
|
||
|
#endregion now the moment we've all been waiting for
|
||
|
|
||
|
#region try to restart services once. If it doesn't work, give up
|
||
|
foreach($processName in $wasRunningProcessNames) {
|
||
|
Write-Host "$logLead : We stopped [$processName] to do the port configuration, trying to start it if it was a service"
|
||
|
# Start-AlkamiService doesn't care if it wasn't actually a service if we SilentlyContinue
|
||
|
Start-AlkamiService -ServiceName $processName -ErrorAction SilentlyContinue
|
||
|
}
|
||
|
#endregion try to restart services once. If it doesn't work, give up
|
||
|
}
|