PowerShell: PowerShell ps1 script to manage bluetooth status stopped working

Prerequisites

Steps to reproduce

Run this script in PowerShell 7.2.1: https://superuser.com/a/1293303/298707

[CmdletBinding()] Param (
    [Parameter(Mandatory=$true)][ValidateSet('Off', 'On')][string]$BluetoothStatus
)
If ((Get-Service bthserv).Status -eq 'Stopped') { Start-Service bthserv }
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$asTaskGeneric = ([System.WindowsRuntimeSystemExtensions].GetMethods() | ? { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' })[0]
Function Await($WinRtTask, $ResultType) {
    $asTask = $asTaskGeneric.MakeGenericMethod($ResultType)
    $netTask = $asTask.Invoke($null, @($WinRtTask))
    $netTask.Wait(-1) | Out-Null
    $netTask.Result
}
[Windows.Devices.Radios.Radio,Windows.System.Devices,ContentType=WindowsRuntime] | Out-Null
[Windows.Devices.Radios.RadioAccessStatus,Windows.System.Devices,ContentType=WindowsRuntime] | Out-Null
Await ([Windows.Devices.Radios.Radio]::RequestAccessAsync()) ([Windows.Devices.Radios.RadioAccessStatus]) | Out-Null
$radios = Await ([Windows.Devices.Radios.Radio]::GetRadiosAsync()) ([System.Collections.Generic.IReadOnlyList[Windows.Devices.Radios.Radio]])
$bluetooth = $radios | ? { $_.Kind -eq 'Bluetooth' }
[Windows.Devices.Radios.RadioState,Windows.System.Devices,ContentType=WindowsRuntime] | Out-Null
Await ($bluetooth.SetStateAsync($BluetoothStatus)) ([Windows.Devices.Radios.RadioAccessStatus]) | Out-Null

With either option .\bluetooth.ps1 -BluetoothStatus On or .\bluetooth.ps1 -BluetoothStatus Off.

Expected behavior

Run like in older PowerShell versions.

Actual behavior

Does not work.

Error details

Get-Error

Exception             :
    Type        : System.Management.Automation.RuntimeException
    ErrorRecord :
        Exception             :
            Type    : System.Management.Automation.ParentContainsErrorRecordException
            Message : You cannot call a method on a null-valued expression.
            HResult : -2146233087
        CategoryInfo          : InvalidOperation: (:) [], ParentContainsErrorRecordException
        FullyQualifiedErrorId : InvokeMethodOnNull
        InvocationInfo        :
            ScriptLineNumber : 19
            OffsetInLine     : 1
            HistoryId        : -1
            ScriptName       : C:\bin\bluetooth.ps1
            Line             : Await ($bluetooth.SetStateAsync($BluetoothStatus))
([Windows.Devices.Radios.RadioAccessStatus]) | Out-Null

            PositionMessage  : At C:\bin\bluetooth.ps1:19 char:1
                               + Await ($bluetooth.SetStateAsync($BluetoothStatus))
([Windows.Devices. …
                               +
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            PSScriptRoot     : C:\bin
            PSCommandPath    : C:\bin\bluetooth.ps1
            CommandOrigin    : Internal
        ScriptStackTrace      : at <ScriptBlock>, C:\bin\bluetooth.ps1: line 19
                                at <ScriptBlock>, <No file>: line 1
    TargetSite  : System.Object CallSite.Target(System.Runtime.CompilerServices.Closure,
System.Runtime.CompilerServices.CallSite, System.Object, System.Object)
    Message     : You cannot call a method on a null-valued expression.
    Data        : System.Collections.ListDictionaryInternal
    Source      : Anonymously Hosted DynamicMethods Assembly
    HResult     : -2146233087
    StackTrace  :
   at CallSite.Target(Closure , CallSite , Object , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame
frame)
CategoryInfo          : InvalidOperation: (:) [], RuntimeException
FullyQualifiedErrorId : InvokeMethodOnNull
InvocationInfo        :
    ScriptLineNumber : 19
    OffsetInLine     : 1
    HistoryId        : -1
    ScriptName       : C:\bin\bluetooth.ps1
    Line             : Await ($bluetooth.SetStateAsync($BluetoothStatus))
([Windows.Devices.Radios.RadioAccessStatus]) | Out-Null

    PositionMessage  : At C:\bin\bluetooth.ps1:19 char:1
                       + Await ($bluetooth.SetStateAsync($BluetoothStatus)) ([Windows.Devices. …
                       + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    PSScriptRoot     : C:\bin
    PSCommandPath    : C:\bin\bluetooth.ps1
    CommandOrigin    : Internal
ScriptStackTrace      : at <ScriptBlock>, C:\bin\bluetooth.ps1: line 19
                        at <ScriptBlock>, <No file>: line 1

Environment data

$PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.2.1
PSEdition                      Core
GitCommitId                    7.2.1
OS                             Microsoft Windows 10.0.22000
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 21

Most upvoted comments

They haven’t removed cmd.exe or Wscript yet, so it’s a bit early to be worrying about Windows PowerShell being removed.

@SeeminglyScience that’s good if you know the script will run in 7.2 but it won’t run natively on 5. That’s why I dropped back to saying “run the same command line in PowerShell.exe” and if the script is in the middle of a pipeline that won’t work.

@superbonaci see the end of my previous comment for how to do that.