Как я могу ссылаться на Windows 8 Runtime (в частности, BLE API) в консольном приложении?
Я использую C# в Visual Studio Professional 13 на Windows 8.1 с установленным WDK.
Мне нужно написать настольное приложение, которое взаимодействует с устройством BLE, используя пользовательский UUID службы. Используя образец общего профиля Bluetooth - пример проекта службы сердечного ритма, доступный в MSDN, я могу отредактировать UUID службы, в котором выполняется поиск, и найти свое конкретное устройство.
Тем не менее, образец проекта представляет собой приложение для Магазина Windows (Metro), и мне нужно консольное приложение.
Когда я создаю новый проект типа Visual C# > Store App > Windows App
Windows 8 SDK автоматически включается в проект.
НО при создании Visual C# > Windows Desktop > *
Проект, я не могу найти способ включить Windows 8 Runtime И BLE API, к которому мне нужно получить доступ.
Конечно, Microsoft не была так близорука, чтобы ограничить BLE API для хранения приложений? Как создать / изменить свой проект для разработки настольных и консольных приложений, использующих BLE API?
Исследования (и неудачные попытки), которые я провел до сих пор, уже исключили 32feet.net, поскольку библиотека в настоящее время не обеспечивает поддержку низкоэнергетического стека Bluetooth.
Однако, если есть другая сторонняя библиотека (желательно с открытым исходным кодом или, по крайней мере, одна с пробной версией), которая обеспечивает поддержку BLE, я был бы открыт для ее использования вместо среды выполнения Windows 8.
2 ответа
Можно вызывать API WinRT из настольных приложений Win32 в Windows 8.x, но это не проверенный или, что более важно, хорошо документированный сценарий.
В C# вы должны вручную добавить ссылки на проект и время выполнения, чтобы это работало. Этот блог подробно описывает это. Короче говоря, чтобы вкладка "Ядро" появлялась в настройках вашего проекта, вам нужно вручную добавить это в ваш проект Visual Studio для MSDN.
<PropertyGroup>
<TargetPlatformVersion>8.0</TargetPlatformVersion>
</PropertyGroup>
Затем вручную добавьте ссылку как на System.Runtime.dll, так и на System.Runtime.InteropServices.WindowsRuntime.dll.
Кстати, для C++ вы можете использовать пространства имен ABI для вызова функций WinRT (как я это делал в одном случае в DirectXTK для аудио) или вы можете использовать расширения 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 или более ранней версии.
Создайте Portable Class Library и поместите туда весь свой BLE-код, а затем ссылайтесь на библиотеку в своем настольном / консольном приложении.