c# - 如何在控制台应用程序中引用 Windows 8 运行时(特别是 BLE API)?

标签 c# windows visual-studio-2013 bluetooth-lowenergy

我在 Windows 8.1 的 Visual Studio Professional 13 中使用 C# 和 WDK 已安装。

我需要编写一个使用自定义服务 UUID 与 BLE 设备交互的桌面应用程序。使用 Bluetooth Generic Attribute Profile - Heart Rate Service 示例项目可从 MSDN 获得,我能够编辑正在搜索的服务 UUID 并找到我的特定设备。

但是,示例项目是一个 Windows Store (Metro) 应用程序,我需要一个控制台应用程序。

当我创建类型为 Visual C# > Store App > Windows App 的新项目时,Windows 8 SDK 会自动包含在该项目中。

但是在创建 Visual C# > Windows Desktop > * 项目时,我找不到包含 Windows 8 运行时和 BLE API 的方法 我需要访问。

当然,Microsoft 并没有短视到将 BLE API 限制在商店应用程序上?如何创建/修改他们的项目以开发利用 BLE API 的桌面和控制台应用程序?

我到目前为止所做的研究(和失败的尝试)已经排除了 32feet.net 因为该库目前不提供对蓝牙低功耗堆栈的支持。

但是,如果有另一个提供 BLE 支持的第 3 方库(最好是开源的,或者至少有一个试用版),我愿意使用它来代替 Windows 8 运行时。

最佳答案

可以从 Windows 8.x 上的 Win32 桌面应用程序调用 WinRT API,但这不是一个经过充分测试或更重要的是没有很好记录的场景。

使用 C#,您必须手动添加项目和运行时引用才能使其正常工作。这blog post详细介绍了它。简而言之,要让“核心”选项卡出现在您的项目设置中,您需要根据 MSDN 将其手动添加到您的 Visual Studio 项目中。 .

<PropertyGroup>
    <TargetPlatformVersion>8.0</TargetPlatformVersion>
</PropertyGroup>

然后手动添加对 System.Runtime.dll 和 System.Runtime.InteropServices.WindowsRuntime.dll 的引用。

顺便说一句,对于 C++,您可以使用 ABI 命名空间来调用 WinRT 函数(例如我在 DirectXTK for Audio 中的一个案例中所做的)或者您可以使用 C++/CX 扩展。

#if defined(__cplusplus_winrt)

    // Enumerating with WinRT using C++/CX (Windows Store apps)
    using Windows::Devices::Enumeration::DeviceClass;
    using Windows::Devices::Enumeration::DeviceInformation;
    using Windows::Devices::Enumeration::DeviceInformationCollection;

    auto operation = DeviceInformation::FindAllAsync(DeviceClass::AudioRender);
    while (operation->Status != Windows::Foundation::AsyncStatus::Completed)
        ;

    DeviceInformationCollection^ devices = operation->GetResults();

    for (unsigned i = 0; i < devices->Size; ++i)
    {
        using Windows::Devices::Enumeration::DeviceInformation;

        DeviceInformation^ d = devices->GetAt(i);
...
    }
#else

    // Enumerating with WinRT using WRL (Win32 desktop app for Windows 8.x)
    using namespace Microsoft::WRL;
    using namespace Microsoft::WRL::Wrappers;
    using namespace ABI::Windows::Foundation;
    using namespace ABI::Windows::Foundation::Collections;
    using namespace ABI::Windows::Devices::Enumeration;

    RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
    HRESULT hr = initialize;
    ThrowIfFailed( hr );

    Microsoft::WRL::ComPtr<IDeviceInformationStatics> diFactory;
    hr = ABI::Windows::Foundation::GetActivationFactory( HStringReference(RuntimeClass_Windows_Devices_Enumeration_DeviceInformation).Get(), &diFactory );
    ThrowIfFailed( hr );

    Event findCompleted( CreateEventEx( nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS ) );
    if ( !findCompleted.IsValid() )
        throw std::exception( "CreateEventEx" );

    auto callback = Callback<IAsyncOperationCompletedHandler<DeviceInformationCollection*>>(
        [&findCompleted,list]( IAsyncOperation<DeviceInformationCollection*>* aDevices, AsyncStatus status ) -> HRESULT
    {
        UNREFERENCED_PARAMETER(aDevices);
        UNREFERENCED_PARAMETER(status);
        SetEvent( findCompleted.Get() );
        return S_OK;
    });

    ComPtr<IAsyncOperation<DeviceInformationCollection*>> operation;
    hr = diFactory->FindAllAsyncDeviceClass( DeviceClass_AudioRender, operation.GetAddressOf() );
    ThrowIfFailed( hr );

    operation->put_Completed( callback.Get() );

    (void)WaitForSingleObjectEx( findCompleted.Get(), INFINITE, FALSE );

    ComPtr<IVectorView<DeviceInformation*>> devices;
    operation->GetResults( devices.GetAddressOf() );

    unsigned int count = 0;
    hr = devices->get_Size( &count );
    ThrowIfFailed( hr );

    if ( !count )
        return list;

    for( unsigned int j = 0; j < count; ++j )
    {
        ComPtr<IDeviceInformation> deviceInfo;
        hr = devices->GetAt( j, deviceInfo.GetAddressOf() );
        if ( SUCCEEDED(hr) )
        {
            HString id;
            deviceInfo->get_Id( id.GetAddressOf() );

            HString name;
            deviceInfo->get_Name( name.GetAddressOf() );
...
        }
    }

#endif 

这当然是只与 Windows 8.0 或更高版本兼容的代码,不会在 Windows 7 或更早版本上运行。

关于c# - 如何在控制台应用程序中引用 Windows 8 运行时(特别是 BLE API)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24843102/

相关文章:

c# - 如何在 Visual Studio 中查看下载包的源代码

c# - 在 C# 中将 XML 空日期反序列化为 DateTime

c# - 在 MVC3 中的每个 Action 之前运行一个方法

windows - DynamoDb SocketException : A socket operation was attempted to an unreachable network

windows - 在 Windows 中循环查找隐藏文件夹

c# - visual studio 2013 突出整个词

visual-studio-2013 - 如何将IIS Express的端口号配置为8080以外的其他端口。

c# - 已删除 用户在其他浏览器上删除后仍登录

c# - 如何在linq中包含()嵌套子实体

linux - GUI报告工具可从Postgresql挖掘数据并创建报告