ぷろじぇくと、みすじら。

UWP API経由でBluetooth LEの通知(Notify)をデスクトップアプリで受け取れない問題

Created at:

以前、CC2650STK SensorTagをUniversal Windows Platform APIから使うというエントリを書いたのですが、最近Creators Update以降(というかInsider Preview)で実行したところ通知が動かなくなっていました。

UWPアプリからは問題なく動くのですが、UWP APIを使う通常のいわゆるクラシックデスクトップアプリからはRead/Writeは正常に行えるもののデバイス側からNotify(通知)を受け取ることができなくなっていていました。

要するにコンソールアプリなどでは GattCharacteristic.WriteClientCharacteristicConfigurationDescriptorAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify) を呼び出したにも関わらず ValueChanged イベントが発生しないという状況です。

解決方法

問題の解決方法ですが起動時に CoInitializeSecurity を呼び出すというおまじないを書くと動くようになります。

CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, RpcAuthnLevel.Default, RpcImpLevel.Identify, IntPtr.Zero, EoAuthnCap.None, IntPtr.Zero);
[DllImport("ole32.dll")]
static extern int CoInitializeSecurity(IntPtr pVoid, int
    cAuthSvc, IntPtr asAuthSvc, IntPtr pReserved1, RpcAuthnLevel level,
    RpcImpLevel impers, IntPtr pAuthList, EoAuthnCap dwCapabilities, IntPtr
    pReserved3);

public enum RpcAuthnLevel
{
    Default = 0,
    None = 1,
    Connect = 2,
    Call = 3,
    Pkt = 4,
    PktIntegrity = 5,
    PktPrivacy = 6
}

public enum RpcImpLevel
{
    Default = 0,
    Anonymous = 1,
    Identify = 2,
    Impersonate = 3,
    Delegate = 4
}

public enum EoAuthnCap
{
    None = 0x00,
    MutualAuth = 0x01,
    StaticCloaking = 0x20,
    DynamicCloaking = 0x40,
    AnyAuthority = 0x80,
    MakeFullSIC = 0x100,
    Default = 0x800,
    SecureRefs = 0x02,
    AccessControl = 0x04,
    AppID = 0x08,
    Dynamic = 0x10,
    RequireFullSIC = 0x200,
    AutoImpersonate = 0x400,
    NoCustomMarshal = 0x2000,
    DisableAAA = 0x1000
}

あまり真面目に追っていないのでおまじない感がすごいですが一応通知が来るようになりました。ちなみにLINQPadからの実行の場合にはうまくいかない可能性が高いです(多分Windows Runtimeの初期化が先に走ってしまったり、再利用されたりなど)。

Windows 10 Insider Preview Build 16273以降

と、調べて解決して、このエントリーを書いた今日、Insider Previewの新しいビルドが来たので更新したところなんと CoInitializeSecurity 呼ばなくても動くように直っていました…oh…。

とりあえず何事もなく動くようになったのでよかったよかったということで…。