LoopbackAdapter.psm1
<# .SYNOPSIS Install a new Loopback Network Adapter. .DESCRIPTION Uses Chocolatey to download the DevCon (Windows Device Console) package and uses it to install a new Loopback Network Adapter with the name specified. The Loopback Adapter will need to be configured like any other adapter (e.g. configure IP and DNS) .PARAMETER Name The name of the Loopback Adapter to create. .PARAMETER Force Force the install of Chocolatey and the Devcon.portable package if not already installed, without confirming with the user. .EXAMPLE $Adapter = New-LoopbackAdapter -Name 'MyNewLoopback' Creates a new Loopback Adapter called MyNewLoopback. .OUTPUTS Returns the newly created Loopback Adapter. .COMPONENT LoopbackAdapter #> function New-LoopbackAdapter { [OutputType([Microsoft.Management.Infrastructure.CimInstance])] [CmdLetBinding()] param ( [Parameter( Mandatory=$true, Position=0)] [string] $Name, [switch] $Force ) $null = $PSBoundParameters.Remove('Name') # Check for the existing Loopback Adapter $Adapter = Get-NetAdapter ` -Name $Name ` -ErrorAction SilentlyContinue # Is the loopback adapter installed? if ($Adapter) { Throw "A Network Adapter $Name is already installed." } # if # Make sure DevCon is installed. $DevConExe = (Install-Devcon @PSBoundParameters).Name # Get a list of existing Loopback adapters # This will be used to figure out which adapter was just added $ExistingAdapters = (Get-LoopbackAdapter).PnPDeviceID # Use Devcon.exe to install the Microsoft Loopback adapter # Requires local Admin privs. $null = & $DevConExe @('install',"$($ENV:SystemRoot)\inf\netloop.inf",'*MSLOOP') # Find the newly added Loopback Adapter $Adapter = Get-NetAdapter ` | Where-Object { ($_.PnPDeviceID -notin $ExistingAdapters ) -and ` ($_.DriverDescription -eq 'Microsoft KM-TEST Loopback Adapter') } if (-not $Adapter) { Throw "The new Loopback Adapter was not found." } # if # Rename the new Loopback adapter $Adapter | Rename-NetAdapter ` -NewName $Name ` -ErrorAction Stop # Set the metric to 254 Set-NetIPInterface ` -InterfaceAlias $Name ` -InterfaceMetric 254 ` -ErrorAction Stop # Wait till IP address binding has registered in the CIM subsystem. # if after 30 seconds it has not been registered then throw an exception. [Boolean] $AdapterBindingReady = $false [DateTime] $StartTime = Get-Date while (-not $AdapterBindingReady ` -and (((Get-Date) - $StartTime).TotalSeconds) -lt 30) { try { $IPAddress = Get-CimInstance ` -ClassName MSFT_NetIPAddress ` -Namespace ROOT/StandardCimv2 ` -Filter "((InterfaceAlias = '$Name') AND (AddressFamily = 2))" ` -ErrorAction Stop if ($IPAddress) { $AdapterBindingReady = $true } # if Start-Sleep -Seconds 1 } catch { } } # while if (-not $IPAddress) { Throw "The New Loopback Adapter was not found in the CIM subsystem." } # Pull the newly named adapter (to be safe) $Adapter = Get-NetAdapter ` -Name $Name ` -ErrorAction Stop Return $Adapter } # function New-LoopbackAdapter <# .SYNOPSIS Returns a specified Loopback Network Adapter or all Loopback Adapters. .DESCRIPTION This function will return either the Loopback Adapter specified in the $Name parameter or all Loopback Adapters. It will only return adapters that use the Microsoft KM-TEST Loopback Adapter driver. This function does not use Chocolatey or the DevCon (Device Console) application, so does not require administrator access. .PARAMETER Name The name of the Loopback Adapter to return. If not specified will return all Loopback Adapters. .EXAMPLE $Adapter = Get-LoopbackAdapter -Name 'MyNewLoopback' Returns the Loopback Adapter called MyNewLoopback. If this Loopback Adapter does not exist or does not use the Microsoft KM-TEST Loopback Adapter driver then an exception will be thrown. .OUTPUTS Returns a specific Loopback Adapter or all Loopback adapters. .COMPONENT LoopbackAdapter #> function Get-LoopbackAdapter { [OutputType([Microsoft.Management.Infrastructure.CimInstance[]])] [CmdLetBinding()] param ( [Parameter( Position=0)] [string] $Name ) # Check for the existing Loopback Adapter if ($Name) { $Adapter = Get-NetAdapter ` -Name $Name ` -ErrorAction Stop if ($Adapter.DriverDescription -ne 'Microsoft KM-TEST Loopback Adapter') { Throw "The Network Adapter $Name exists but it is not a Microsoft KM-TEST Loopback Adapter." } # if return $Adapter } else { Get-NetAdapter | Where-Object -Property DriverDescription -eq 'Microsoft KM-TEST Loopback Adapter' } # if } # function Get-LoopbackAdapter <# .SYNOPSIS Uninstall an existing Loopback Network Adapter. .DESCRIPTION Uses Chocolatey to download the DevCon (Windows Device Console) package and uses it to uninstall a new Loopback Network Adapter with the name specified. .PARAMETER Name The name of the Loopback Adapter to uninstall. .PARAMETER Force Force the install of Chocolatey and the Devcon.portable package if not already installed, without confirming with the user. .EXAMPLE Remove-LoopbackAdapter -Name 'MyNewLoopback' Removes an existing Loopback Adapter called MyNewLoopback. .OUTPUTS None .COMPONENT LoopbackAdapter #> function Remove-LoopbackAdapter { [CmdLetBinding()] param ( [Parameter( Mandatory=$true, Position=0)] [string] $Name, [switch] $Force ) $null = $PSBoundParameters.Remove('Name') # Check for the existing Loopback Adapter $Adapter = Get-NetAdapter ` -Name $Name ` -ErrorAction SilentlyContinue # Is the loopback adapter installed? if (! $Adapter) { # Adapter doesn't exist Throw "Loopback Adapter $Name is not found." } # Is the adapter Loopback adapter? if ($Adapter.DriverDescription -ne 'Microsoft KM-TEST Loopback Adapter') { # Not a loopback adapter - don't uninstall this! Throw "Network Adapter $Name is not a Microsoft KM-TEST Loopback Adapter." } # if # Make sure DevCon is installed. $DevConExe = (Install-Devcon @PSBoundParameters).Name # Use Devcon.exe to remove the Microsoft Loopback adapter using the PnPDeviceID. # Requires local Admin privs. $null = & $DevConExe @('remove',"@$($Adapter.PnPDeviceID)") } # function Remove-LoopbackAdapter # Support functions - not exposed <# .SYNOPSIS Install the DevCon.Portable (Windows Device Console) package using Chocolatey. .DESCRIPTION Installs Chocolatey from the internet if it is not installed, then uses it to download the DevCon.Portable (Windows Device Console) package. The devcon.portable Chocolatey package can be found here and installed manually if no internet connection is available: https://chocolatey.org/packages/devcon.portable/ Chocolatey will remain installed after this function is called. .PARAMETER Force Force the install of Chocolatey and the Devcon.portable package if not already installed, without confirming with the user. .EXAMPLE Install-Devcon .OUTPUTS The fileinfo object containing the appropriate DevCon*.exe application that was installed for this architecture. .COMPONENT LoopbackAdapter #> function Install-Devcon { [OutputType([System.IO.FileInfo])] [CmdLetBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Switch] $Force ) Install-Chocolatey @PSBoundParameters # Check DevCon installed - if not, install it. $DevConInstalled = ((Test-Path -Path "$ENV:ProgramData\Chocolatey\Lib\devcon.portable\Devcon32.exe") ` -and (Test-Path -Path "$ENV:ProgramData\Chocolatey\Lib\devcon.portable\Devcon64.exe")) if (! $DevConInstalled) { try { # This will download and install DevCon.exe # It will also be automatically placed into the path If ($Force -or $PSCmdlet.ShouldProcess('Download and install DevCon (Windows Device Console) using Chocolatey')) { $null = & choco install -r -y devcon.portable } else { Throw 'DevCon (Windows Device Console) was not installed because user declined.' } } catch { Throw 'An error occured installing DevCon (Windows Device Console) using Chocolatey.' } } if ([Environment]::Is64BitOperatingSystem -eq $True) { Get-ChildItem "$ENV:ProgramData\Chocolatey\Lib\devcon.portable\Devcon64.exe" } else { Get-ChildItem "$ENV:ProgramData\Chocolatey\Lib\devcon.portable\Devcon32.exe" } } <# .SYNOPSIS Install the DevCon.Portable (Windows Device Console) package using Chocolatey. .DESCRIPTION Installs Chocolatey from the internet if it is not installed, then uses it to uninstall the DevCon.Portable (Windows Device Console) package. Chocolatey will remain installed after this function is called. .PARAMETER Force Force the uninstall of the devcon.portable package if it is installed, without confirming with the user. .EXAMPLE Uninstall-Devcon .OUTPUTS None. .COMPONENT LoopbackAdapter #> function Uninstall-Devcon { [CmdLetBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Switch] $Force ) Install-Chocolatey @PSBoundParameters try { # This will download and install DevCon.exe # It will also be automatically placed into the path if ($Force -or $PSCmdlet.ShouldProcess('Uninstall DevCon (Windows Device Console) using Chocolatey')) { $null = & choco uninstall -r -y devcon.portable } else { Throw 'DevCon (Windows Device Console) was not uninstalled because user declined.' } } catch { Throw 'An error occured uninstalling DevCon (Windows Device Console) using Chocolatey.' } } <# .SYNOPSIS Install Chocolatey. .DESCRIPTION Installs Chocolatey from the internet if it is not installed.d. .PARAMETER Force Force the install of Chocolatey, without confirming with the user. .EXAMPLE Install-Chocolatey .OUTPUTS None .COMPONENT LoopbackAdapter #> function Install-Chocolatey { [CmdLetBinding( SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Switch] $Force ) # Check chocolatey is installed - if not, install it $ChocolateyInstalled = Test-Path -Path (Join-Path -Path $ENV:ProgramData -ChildPath 'Chocolatey\Choco.exe') if (! $ChocolateyInstalled) { If ($Force -or $PSCmdlet.ShouldProcess('Download and install Chocolatey')) { $null = Invoke-Expression ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')) } else { Throw 'Chocolatey could not be installed because user declined installation.' } } } |