Public/Wifi/Connect-WifiNetwork.ps1
|
Function Connect-WiFiNetwork { <# .SYNOPSIS Connects one, multiple, or all WiFi adapters to a specific network (SSID). .DESCRIPTION This function uses the WinRT API to connect. It supports simultaneously targeting specific adapters by their index. If a network is already known to Windows (profile exists), the password is not required. .PARAMETER Ssid Mandatory The name of the WiFi network. Use the TAB key for suggestions of available nearby networks. .PARAMETER Password Optional The password for the network. This is a dynamic parameter that uses SecureString (unless -AsPlainText is specified). Not required if a stored profile already exists. .PARAMETER Index Optional The index of the adapter(s) (e.g., 0, 1). Leave this blank to attempt the connection on ALL available WiFi adapters simultaneously. .PARAMETER User Optional username for enterprise networks (802.1X). .PARAMETER Bssid Optional Force connection to a specific Access Point based on the MAC address. .EXAMPLE Connect-WiFiNetwork -Ssid "MyHomeNetwork" -Index 0 Connects the first adapter to the specified network. .EXAMPLE Connect-WiFiNetwork -Ssid "Open_WiFi" Attempts to connect all WiFi adapters on the system to an open network. .EXAMPLE Connect-WiFiNetwork -Ssid "Company_WiFi" -Password (Read-Host -AsSecureString) -Index 0, 2 Connects adapter 0 and 2 to a secured network with manual password input. .NOTES The function checks each adapter to ensure the SSID is visible before initiating the connection. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)]$Ssid, [string]$Bssid, [string]$User, [Switch]$AsPlainText, [Switch]$Hidden, [int[]]$Index, [Int]$TimeoutMS = 120000, [Windows.Devices.WiFi.WiFiReconnectionKind]$WifiReconnectionKind = [Windows.Devices.WiFi.WiFiReconnectionKind]::Automatic ) DynamicParam { # Choice type depending on Switch $parameterType = if ($AsPlainText) { [string] } else { [securestring] } # Create the attributeCollection for all attributes like Mandatory $attributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $attribute = New-Object System.Management.Automation.ParameterAttribute $attribute.Mandatory = $false $attributeCollection.Add($attribute) # Define the 'Password' paramter at runtime $dynParam = New-Object System.Management.Automation.RuntimeDefinedParameter('Password', $parameterType, $attributeCollection) # Add to the Dictionary wich powreshell expects to receive $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $paramDictionary.Add('Password', $dynParam) return $paramDictionary } Process { # --- 1. PERMISSIE & RADIO CHECK --- if ((Request-LocationPermission) -ne 'Allowed') { return } $Adapters = Get-WiFiAvailableAdapter if (-not $Adapters) { throw "No active WiFi-adapter found." } # Radio check (Simpeler geschreven) $Radios = Get-RadioState | Where-Object Kind -eq 'WiFi' if ($Radios.Count -gt 0 -and -not ($Radios | Where-Object State -eq 'On')) { throw "Error: All WiFi radios are OFF. Turn them on first." } # --- 2. Prepair Credentials --- $Pass = $PSBoundParameters['Password'] $Creds = [Windows.Security.Credentials.PasswordCredential]::new() if ($null -ne $Pass) { if ($AsPlainText) { $Creds.Password = $Pass } else { $Creds.Password = ([System.Net.NetworkCredential]::new("", $Pass)).Password } } if ($User) { $Creds.UserName = $User } # --- 3. Getting the adapters you want to control --- $Targets = if ($PSBoundParameters.ContainsKey('Index')) { $Index | ForEach-Object { $Adapters[$_] } } else { $Adapters } # --- 4. Connection Loop --- $Targets | ForEach-Object { $currentId = $_.NetworkAdapter.NetworkAdapterId $name = (Get-NetAdapter | Where-Object DeviceID -match $currentId).InterfaceDescription # Search the network specifick for this $Net = $_.NetworkReport.AvailableNetworks | Where-Object { if ($Bssid) { $_.Bssid -eq $Bssid } else { $_.Ssid -eq $Ssid } } | Sort-Object NetworkRssiInDecibelMilliwatts -Descending | Select-Object -First 1 if (-not $Net -and -not $Hidden) { # Force Scan if not found $null = Search-WifiNetworksPrivate $Net = $_.NetworkReport.AvailableNetworks | Where-Object { if ($Bssid) { $_.Bssid -eq $Bssid } else { $_.Ssid -eq $Ssid } } | Select-Object -First 1 } if (-not $Net) { Write-Warning "Adapter $($name): SSID '$($Ssid)' not found."; return } Write-Host "Connecting $name to $Ssid..." -ForegroundColor Cyan $_.Disconnect() $_Ssid = $null if ($Hidden) { $_Ssid = $Ssid # Pass the SSID if it's a hidden network } $Task = $_.ConnectAsync($Net, $WifiReconnectionKind, $Creds, $_Ssid) $Res = AwaitWithCancel -WinRtTask $Task -ResultType ([Windows.Devices.WiFi.WiFiConnectionResult]) -TimeoutMs $TimeoutMS -Activity "Connecting $Ssid" # Output [PSCustomObject]@{ ConnectionStatus = $Res.ConnectionStatus AdapterName = $name Ssid = $Ssid Bssid = $Net.Bssid } } } } Register-ArgumentCompleter -CommandName 'Connect-WiFiNetwork' -ParameterName 'Index' -ScriptBlock $ScriptBlockArgumentCompleterIndex Register-ArgumentCompleter -CommandName 'Connect-WiFiNetwork' -ParameterName 'Bssid' -ScriptBlock $ScriptBlockArgumentCompleterBssid Register-ArgumentCompleter -CommandName 'Connect-WiFiNetwork' -ParameterName 'Ssid' -ScriptBlock $ScriptBlockArgumentCompleterSsid Register-ArgumentCompleter -CommandName 'Connect-wifiNetwork' -ParameterName 'WifiReconnectionKind' -ScriptBlock $ScriptBlockArgumentCompleterWifiReconnectionKind |