Public/network/Remove-NetworkRoute.ps1

#Requires -Version 5.1

function Remove-NetworkRoute {
    <#
        .SYNOPSIS
            Removes an IP route from the routing table on one or more Windows computers
 
        .DESCRIPTION
            Deletes a route from the routing table using the Remove-NetRoute cmdlet.
            The route is identified by its destination prefix and optionally by interface
            and next hop.
 
            Requires Administrator privileges.
 
            For remote computers, the operation is executed via Invoke-Command, which
            requires WinRM / WS-Man enabled on the target.
 
        .PARAMETER ComputerName
            One or more computer names to configure. Accepts pipeline input by value and
            by property name. Defaults to the local machine ($env:COMPUTERNAME).
 
        .PARAMETER Credential
            Optional PSCredential for authenticating to remote machines. Ignored for
            local machine operations.
 
        .PARAMETER DestinationPrefix
            The destination prefix of the route to remove (e.g. '10.0.0.0/8').
 
        .PARAMETER InterfaceIndex
            The interface index to narrow which route to remove.
 
        .PARAMETER InterfaceAlias
            The interface alias to narrow which route to remove. Alternative to InterfaceIndex.
 
        .PARAMETER NextHop
            Optional next hop address to narrow route selection when multiple routes
            share the same destination prefix.
 
        .EXAMPLE
            Remove-NetworkRoute -DestinationPrefix '10.10.0.0/16' -InterfaceAlias 'Ethernet'
 
            Removes the route to 10.10.0.0/16 on the Ethernet interface.
 
        .EXAMPLE
            Remove-NetworkRoute -DestinationPrefix '10.10.0.0/16' -InterfaceAlias 'Ethernet' -NextHop '192.168.1.1'
 
            Removes a specific route identified by destination, interface and next hop.
 
        .EXAMPLE
            'SRV01', 'SRV02' | Remove-NetworkRoute -DestinationPrefix '10.10.0.0/16' -InterfaceAlias 'Ethernet'
 
            Removes the route on two remote servers via pipeline.
 
        .OUTPUTS
            None
            This function does not produce pipeline output.
 
        .NOTES
            Author: Franck SALLET
            Version: 1.0.0
            Last Modified: 2026-03-20
            Requires: PowerShell 5.1+ / Windows only
            Permissions: Administrator privileges required
            Remote: Requires WinRM / WS-Man enabled on target machines
 
        .LINK
            https://github.com/k9fr4n/PSWinOps
 
        .LINK
            https://learn.microsoft.com/en-us/powershell/module/nettcpip/remove-netroute
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
    [OutputType([void])]
    param(
        [Parameter(Mandatory = $false,
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [Alias('CN', 'Name', 'DNSHostName')]
        [string[]]$ComputerName = $env:COMPUTERNAME,

        [Parameter(Mandatory = $false)]
        [PSCredential]$Credential,

        [Parameter(Mandatory = $true)]
        [ValidateNotNullOrEmpty()]
        [string]$DestinationPrefix,

        [Parameter(Mandatory = $false)]
        [ValidateRange(1, 999999)]
        [int]$InterfaceIndex,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$InterfaceAlias,

        [Parameter(Mandatory = $false)]
        [ValidateNotNullOrEmpty()]
        [string]$NextHop
    )

    begin {
        Write-Verbose "[$($MyInvocation.MyCommand)] Starting network route removal"
        $localNames = @($env:COMPUTERNAME, 'localhost', '.')
        $hasCredential = $PSBoundParameters.ContainsKey('Credential')

        $queryScriptBlock = {
            param(
                [string]$QDestinationPrefix,
                [int]$QInterfaceIndex,
                [string]$QInterfaceAlias,
                [string]$QNextHop
            )

            $removeParams = @{
                DestinationPrefix = $QDestinationPrefix
                Confirm           = $false
                ErrorAction       = 'Stop'
            }

            if ($QInterfaceIndex -gt 0) {
                $removeParams['InterfaceIndex'] = $QInterfaceIndex
            } elseif ($QInterfaceAlias) {
                $removeParams['InterfaceAlias'] = $QInterfaceAlias
            }

            if ($QNextHop) {
                $removeParams['NextHop'] = $QNextHop
            }

            Remove-NetRoute @removeParams
        }
    }

    process {
        foreach ($targetComputer in $ComputerName) {
            try {
                $isLocal = $localNames -contains $targetComputer
                $shouldProcessTarget = "Route $DestinationPrefix on '$targetComputer'"

                Write-Verbose "[$($MyInvocation.MyCommand)] Removing route on '$targetComputer' (local: $isLocal)"

                if (-not $PSCmdlet.ShouldProcess($shouldProcessTarget, 'Remove network route')) {
                    continue
                }

                $queryArgs = @(
                    $DestinationPrefix
                    $(if ($PSBoundParameters.ContainsKey('InterfaceIndex')) {
                            $InterfaceIndex
                        } else {
                            0
                        })
                    $(if ($PSBoundParameters.ContainsKey('InterfaceAlias')) {
                            $InterfaceAlias
                        } else {
                            $null
                        })
                    $(if ($PSBoundParameters.ContainsKey('NextHop')) {
                            $NextHop
                        } else {
                            $null
                        })
                )

                if ($isLocal) {
                    & $queryScriptBlock @queryArgs
                } else {
                    $invokeParams = @{
                        ComputerName = $targetComputer
                        ScriptBlock  = $queryScriptBlock
                        ArgumentList = $queryArgs
                        ErrorAction  = 'Stop'
                    }
                    if ($hasCredential) {
                        $invokeParams['Credential'] = $Credential
                    }
                    Invoke-Command @invokeParams
                }

                Write-Verbose "[$($MyInvocation.MyCommand)] Route '$DestinationPrefix' removed successfully on '$targetComputer'"
            } catch {
                Write-Error "[$($MyInvocation.MyCommand)] Failed on '$targetComputer': $_"
            }
        }
    }

    end {
        Write-Verbose "[$($MyInvocation.MyCommand)] Completed network route removal"
    }
}