FromBluetoothAddressAsync never returns on Windows 10 Creators Update in WPF Application

混江龙づ霸主 提交于 2019-11-29 14:01:47

It looks like there's a bug in the Security functions around the Bluetooth APIs in 15063 that's causing this (I'm seeing the same thing). Check out this thread:

https://social.msdn.microsoft.com/Forums/en-US/58da3fdb-a0e1-4161-8af3-778b6839f4e1/bluetooth-bluetoothledevicefromidasync-does-not-complete-on-10015063?forum=wdk#ef927009-676c-47bb-8201-8a80d2323a7f

tl;dr For C++ applications, they provide a CoInitializeSecurity function to call. For everyone else, it looks like they're recommending creating an AppId in the registry, since P/Invoke isn't much fun.

Weirdly enough, things are working fine for me at the moment through noble-uwp, which uses C++ bindings to UWP functions for access via node.js. It's only via C# that I'm having issues, and things fail at different points depending on whether I'm in a UWP or WPF/Console/Desktop application.

After adding the AppId to the registry as outlined in the forum post, things worked for me again.

Interestingly, it does work on desktop applications using cppwinrt:

Advertisement::BluetoothLEAdvertisementWatcher watcher;

void Start() {
    watcher.ScanningMode(Advertisement::BluetoothLEScanningMode::Active);
    Windows::Foundation::TimeSpan timeout = std::chrono::seconds(2);
    watcher.SignalStrengthFilter().OutOfRangeTimeout(timeout);
    watcher.SignalStrengthFilter().OutOfRangeThresholdInDBm(-90);

    watcher.Received([&](Advertisement::BluetoothLEAdvertisementWatcher watcher, Advertisement::BluetoothLEAdvertisementReceivedEventArgs eventArgs) {
        connect(eventArgs.BluetoothAddress());
    });
    watcher.Start();
}

Windows::Foundation::IAsyncAction connect(uint64_t uuid) {
    co_await resume_background();
    BluetoothLEDevice device = co_await BluetoothLEDevice::FromBluetoothAddressAsync(uuid);
    GenericAttributeProfile::GattDeviceServicesResult gatt = co_await device.GetGattServicesForUuidAsync(myServiceUUID);
    // works fine!
}

However, notifications for GATT characteristics don't work for me after that. I have filed a bug report with the cppwinrt project, but the devs don't seem to be particularly inclined to look into it.

I have no idea what that API is doing differently than the desktop C# version.

If you wish to use the CoInitializeSecurity solution in VB, here is a pinvoke solution. Remember to unpair/repair all your BLE devices!

Note that is must be the fist thing executed in your code. Note that this is NOT AT ALL secure.

Public Enum RpcAuthnLevel
    Default1 = 0
    None = 1
    Connect = 2
    Call1 = 3
    Pkt = 4
    PktIntegrity = 5
    PktPrivacy = 6
End Enum

Public Enum RpcImpLevel
    Default1 = 0
    Anonymous = 1
    Identify = 2
    Impersonate = 3
    Delegate1 = 4
End Enum

Public Enum EoAuthnCap
    None = &H0
    MutualAuth = &H1
    StaticCloaking = &H20
    DynamicCloaking = &H40
    AnyAuthority = &H80
    MakeFullSIC = &H100
    Default1 = &H800
    SecureRefs = &H2
    AccessControl = &H4
    AppID = &H8
    Dynamic = &H10
    RequireFullSIC = &H200
    AutoImpersonate = &H400
    NoCustomMarshal = &H2000
    DisableAAA = &H1000
End Enum

Declare Function CoInitializeSecurity Lib "ole32.dll" (pVoid As IntPtr, cAuthSvc As Integer, asAuthSvc As IntPtr, pReserved1 As IntPtr, dwAuthnLevel As Integer, dwImpLevel As Integer, pAuthList As IntPtr, dwCapabilities As Integer, pReserved3 As IntPtr) As Integer

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, RpcAuthnLevel.Default1, RpcImpLevel.Identify, IntPtr.Zero, EoAuthnCap.None, IntPtr.Zero)
    'Other code
End Sub
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!