我在 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/