FromBluetoothAddressAsync никогда не возвращается в Windows 10 Creators Update в приложении WPF

Я обновлен до Windows 10, версия 1703 build 15063 (Creators Update) официальный релиз. Когда я запускаю следующий код в настольном приложении WPF, BluetoothLEDevice.FromBluetoothAddressAsync никогда не возвращается.

этот код работал отлично перед моим обновлением Windows 10 (т. е. предыдущим 1607 build 14393). Этот код также отлично работает, если он работает как UWP в новом Win 10 1703.

BluetoothLEAdvertisementWatcher BleWatcher = null;

private void Button_Click(object sender, RoutedEventArgs e)
{
     BleWatcher = new BluetoothLEAdvertisementWatcher
     {
          ScanningMode = BluetoothLEScanningMode.Active
     };
     BleWatcher.Received += Watcher_Received;
     BleWatcher.Start();
}

private async void Watcher_Received(BluetoothLEAdvertisementWatcher sender, 
                                    BluetoothLEAdvertisementReceivedEventArgs args)
{
         var device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress);
         // never continues beyond this point above with my BTLE devices that previously worked 
}

я следовал инструкциям здесь https://stackoverflow.com/a/37335251/3187714 чтобы настроить настольное приложение WPF для использования API UWP.

проблема еще хуже, потому что мое существующее приложение WPF будет сломано, когда клиенты начнут обновление до Win 10 1703, потому что мой существующий exe больше не работает.

кто-нибудь еще испытывает эту проблему с обновлением Windows 10 1703 в (не UWP) desktop exe?

после дальнейших экспериментов, я нашел если я добавил дополнительный BluetoothAddressType.Открытый 2-й аргумент для вызова FromBluetoothAddressAsync, функция возвращена, но возвращаемое устройство было null.

var device = await BluetoothLEDevice.FromBluetoothAddressAsync(args.BluetoothAddress, BluetoothAddressType.Public);

3 ответов


похоже, что есть ошибка в функциях безопасности вокруг API Bluetooth в 15063, которая вызывает это (я вижу то же самое). Проверьте эту тему:

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 для приложений C++ они предоставляют функцию CoInitializeSecurity для вызов. Для всех остальных, похоже, они рекомендуют создать AppId в реестре, так как P / Invoke не очень весело.

Как ни странно, на данный момент все работает нормально для меня через noble-uwp, который использует привязки C++ к функциям UWP для доступа через узел.js. Только через C# у меня возникают проблемы, и вещи терпят неудачу в разные моменты в зависимости от того, нахожусь ли я в UWP или WPF/консоли/настольном приложении.

после добавления AppId в реестр как изложенное в сообщении форума, все снова сработало для меня.


интересно, что он тут работа на настольных приложениях с помощью 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!
}

однако уведомления для характеристик GATT не работают для меня после этого. Я подал сообщение об ошибке С проектом cppwinrt, но разработчики, похоже, не особенно склонны заглядывать в него.

Я понятия не имею, что этот API делает иначе, чем настольная версия c#.


Если вы хотите использовать решение CoInitializeSecurity в VB, вот решение pinvoke. Не забудьте отменить/восстановить все ваши устройства BLE!

обратите внимание, что это должна быть первая вещь, выполненная в вашем коде. Обратите внимание, что это совсем не безопасно.

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