Correct library or runtime for GattDeviceServicesR

2019-07-18 11:27发布

问题:

UPDATE I now have reason to believe that you can't use Windows Creator on Enterprise LTSB because the version isn't high enough and can't be updated! If someone could confirm this AND state how I should go about developing a Bluetooth app given that I can use Creator it would be much appreciated.

"Could not find Windows Runtime type 'Windows.Devices.Bluetooth.GenericAttributeProfile.GattDeviceServicesResult'"

I developed some sample code on my developer machine to communicate through BLE (Bluetooth Low Energy) in C#/.Net. When I transfer this release folder to another machine and run the program, I get the message above when I try to initiate BLE communications. I'm guessing that I'm missing some key library/dll (or .NETCore or .Net Framework), but what? I've searched and can't find an answer.

A possibly useful clue (or possibly irrelevant) is that that in my project I have a reference to System.Runtime.WindowsRuntime in directory C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETCore\v4.5.1\System.Runtime.WindowsRuntime.dll The other machine does not have a v4.5.1 but only a v4.5. However, when I try and install v4.5.1 I'm told that I already have a newer version! Perhaps someone could tell me how to get .netcore v4.5.1 on a machine?

Thanks, Dave

More information. In the original project, there is a reference "Windows" with path C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.17134.0\Windows.winmd If you use Object Browser on this you'll see Windows.Devices.Bluetooth.GenericAttributeProfile.GattDeviceServicesResult This same file (same version) is also on the system I'm trying to get my code to run on. Not sure why it's not "seeing" it at run time.

Apparently, others have had this problem. See: Bluetooth LE GattDeviceServicesResult TypeLoadException from WPF application

Yet more information based on research I installed Visual Studio on the production machine thinking that would remove one difference between my developer machine and the production machine. Still no luck. However, I will point out that one of the remaining differences is that my developer machine has Windows 10 Pro. The production machine (which is a Tablet) has Windows 10 Enterprise 2016 LTSB

回答1:

It seems that Windows 10 Enterprise does not support quite a few of the methods in Windows.Devices.Bluetooth namespace. The solution that I found for this requires Windows 10 Enterprise users to pair their BLE devices. This allows us to use the obsolete BluetoothLEDevice.GattServices property. We catch the TypeLoadException and fall back to the methods supported in Windows 10 Enterprise.

    private async Task<IReadOnlyCollection<GattDeviceService>> GetGattService(BluetoothLEDevice device, Guid uuid)
    {
        try
        {
            // Try to get the services async first
            return await GetGattServicesAsync(device, uuid);
        }
        catch(TypeLoadException e)
        {
            // Not supported in version of windows. Fall back to old way
            return GetGattDeviceServices(device, uuid);
        }
    }

    private async Task<IReadOnlyList<GattDeviceService>> GetGattServicesAsync(BluetoothLEDevice device, Guid uuid)
    {
        var result = await Device.GetGattServicesForUuidAsync(uuid);
        if(result.Status == GattCommunicationStatus.Success)
        {
            return result.Services;
        }
        return null;
    }

    private IReadOnlyList<GattDeviceService> GetGattDeviceServices(BluetoothLEDevice device, Guid uuid)
    {
        var result = device.GattServices.Where(s => s.Uuid == uuid);
        if(result != null)
        {
            return result.ToList().AsReadOnly();
        }
        return null;
    }

We need to do the same when attempting to get the characteristics from the services. Instead of calling GattDeviceService.GetCharacteristicsForUuidAsync we call GattDeviceService.GetAllCharacteristics(). I also found instances where some PCs did not support any of the BluetoothLEDevice.GetDeviceSelector() methods, which was causing problems creating the watcher. Having to pair the device is a bit of an inconvenience. Unfortunately I have not been able to find any documentation on this. Other than a couple videos here where they discuss not having to pair BLE devices anymore which led me to believe that it was not supported in LTSB.