I created a PowerShell script to programmatically enable or disable WiFi or Bluetooth radios on a Windows system using the Windows.Devices.Radios
namespace and WinRT APIs. The script handles the asynchronous nature of WinRT APIs and works seamlessly to toggle the radio state.
Below is the implementation for enabling/disabling WiFi or Bluetooth radios.
This PowerShell script enables or disables WiFi or Bluetooth on Windows using the Windows.Devices.Radios
namespace via WinRT APIs. Below is a detailed explanation of the script and how it works.
# script to enable/disable WiFi or bluetooth in Windows
# carsten.giese@googlemail.com
cls
Remove-Variable * -ea 0
$ErrorActionPreference = 'stop'
$newStatus = 'On' # On/Off
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$methods = [System.WindowsRuntimeSystemExtensions].GetMethods()
foreach($m in $methods) {
if ($m.Name -ne 'AsTask') {continue}
if ($m.GetParameters().Count -ne 1) {continue}
if ($m.GetParameters()[0].ParameterType.Name -ne 'IAsyncOperation`1') {continue}
$asTaskGeneric = $m
break
}
function await($task, $type) {
$asTask = $asTaskGeneric.MakeGenericMethod($type)
$netTask = $asTask.Invoke($null, $task)
$null = $netTask.Wait(-1)
$netTask.Result
}
$radio = [Windows.Devices.Radios.Radio]
$rList = [System.Collections.Generic.IReadOnlyList[Windows.Devices.Radios.Radio]]
$status = [Windows.Devices.Radios.RadioAccessStatus]
$null = [Windows.Devices.Radios.Radio,Windows.System.Devices,ContentType=WindowsRuntime]
$null = Await -task $radio::RequestAccessAsync() -type $status
$radios = Await -task $radio::GetRadiosAsync() -type $rList
$wifi = $radios | where {$_.Kind -eq 'WiFi'}
$null = Await -task $wifi.SetStateAsync($newStatus) -type $status
# $bt = $radios | where {$_.Kind -eq 'Bluetooth'}
# $null = Await -task $bt.SetStateAsync($newStatus) -type $status
Setting the Desired Status:
$newStatus
variable is set to 'On'
or 'Off'
to indicate whether the radio (WiFi/Bluetooth) should be enabled or disabled.Loading Required Assemblies:
System.Runtime.WindowsRuntime
assembly, which is necessary for accessing WinRT APIs.Finding the AsTask
Method:
AsTask
method converts asynchronous operations (IAsyncOperation<T>
in WinRT) into .NET Task
objects. The script dynamically identifies the correct overload of AsTask
using reflection.Handling Asynchronous Tasks with Await
:
await
function that:
AsTask
method to convert a WinRT asynchronous operation into a .NET Task
..Wait()
.Requesting Radio Access:
RequestAccessAsync
to request permission for managing radios.Retrieving and Managing Radios:
GetRadiosAsync
method retrieves a list of radios (WiFi, Bluetooth, etc.) available on the system.Kind
property to identify the desired radio (WiFi
or Bluetooth
).SetStateAsync
method is invoked with the desired state ('On'
or 'Off'
) to toggle the radio.WiFi:
$wifi = $radios | where {$_.Kind -eq 'WiFi'}
$null = Await -task $wifi.SetStateAsync($newStatus) -type $status
Bluetooth: (uncomment the following lines to manage Bluetooth)
$bt = $radios | where {$_.Kind -eq 'Bluetooth'}
$null = Await -task $bt.SetStateAsync($newStatus) -type $status
The await
function bridges the gap between WinRT's asynchronous operations and PowerShell's synchronous execution model. Here's why this is important:
WinRT APIs Are Asynchronous by Design:
RequestAccessAsync
and GetRadiosAsync
return IAsyncOperation<T>
objects, which cannot be directly awaited in PowerShell.AsTask
method converts these into .NET Task
objects, enabling synchronous handling.Custom await
Implementation:
await
function uses the identified AsTask
method to handle asynchronous operations. It ensures tasks are completed before proceeding, providing a straightforward synchronous experience for the rest of the script.This script is an excellent example of how PowerShell can interact with modern WinRT APIs for advanced Windows functionality, such as controlling radios programmatically.