Windows-universal-samples 的 Custom Capability 示例:UWP 自定义功能的声明、签名与设备/服务访问实战
示例工程【免费下载链接】Windows-universal-samplesAPI samples for the Universal Windows Platform.项目地址https://gitcode.com/gh_mirrors/wi/Windows-universal-samples点击查看免费下载UWPUniversal Windows Platform应用的能力Capability体系分为普通能力与受限能力两大类而本仓库中的Custom Capability 示例即archived/CustomCapability/README.md所对应的样例演示的是第三类——自定义功能Custom Capabilities由 OEM/驱动开发者自定义、需要在驱动侧授权并通过 SCCD 文件签发的受限能力。通过本文你将掌握如何在应用清单中声明自定义能力、如何用其连接受保护的 NT 服务RPC、如何访问仅对特定应用开放的 OSR USB FX-2 自定义设备IOCTL/流读写/异步事件以及如何借助自定义能力读写 SMBIOS/UEFI 固件变量并了解配套的构建、部署与运行前提。自定义能力Custom Capability是什么普通的 UWP 能力如microphone、picturesLibrary由系统预定义、直接写在清单即可生效受限能力Restricted Capability如smbios、protectedApp则需要特殊授权。而自定义能力是 Windows 10 引入的一种机制能力名称、语义和授权对象全部由能力拥有者通常是硬件驱动开发者或系统服务提供者自行定义并通过一个SCCDCustom Capability Descriptor文件声明哪些应用包按包族名 证书签名哈希被授权使用该能力。archived/CustomCapability/README.md以及当前活跃版本 Samples/CustomCapability/README.md明确指出示例中附带的 SCCD 文件并非有效签名版本仅用于教学演示只要开发机处于“开发者模式”Developer Mode应用依然可以完成部署运行。真正的产品应用中必须按照微软文档“Custom Capabilities for Universal Windows Platform apps”的流程申请并获得正确签名的 SCCD 文件。示例中一共使用了两个自定义能力microsoft.hsaTestCustomCapability_q536wpkpf5cy2用于访问示例 NT 服务与 OSR FX-2 自定义设备microsoft.firmwareRead_cw5n1h2txyewy/microsoft.firmwareWrite_cw5n1h2txyewy用于读写 UEFI 固件变量。从随附的 SCCD 文件可以直观看到能力描述符的结构archived/CustomCapability/js/CustomCapability.SCCDC 版本见 Samples/CustomCapability/cpp/CustomCapability.SCCD?xml version1.0 encodingutf-8? CustomCapabilityDescriptor xmlnshttp://schemas.microsoft.com/appx/2016/sccd xmlns:shttp://schemas.microsoft.com/appx/2016/sccd CustomCapabilities CustomCapability Namemicrosoft.firmwareRead_cw5n1h2txyewy/CustomCapability CustomCapability Namemicrosoft.hsaTestCustomCapability_q536wpkpf5cy2/CustomCapability /CustomCapabilities AuthorizedEntities AuthorizedEntity AppPackageFamilyNameMicrosoft.SDKSamples.CustomCapability.JS_8wekyb3d8bbwe CertificateSignatureHashca9fc964db7e0c2938778f4559946833e7a8cfde0f3eaa07650766d4764e86c4/AuthorizedEntity AuthorizedEntity AppPackageFamilyNameMicrosoft.SDKSamples.CustomCapability.JS_8wekyb3d8bbwe CertificateSignatureHashc39c58eff76e19113531f0776e2f5b7c34e5172f5d62aa31482f9e37b32ec242/AuthorizedEntity /AuthorizedEntities Catalogxxxx/Catalog /CustomCapabilityDescriptor其语义是声明两个自定义能力CustomCapabilities节点并声明两个授权实体AuthorizedEntities节点——每个实体由AppPackageFamilyName应用包族名与CertificateSignatureHash签名证书哈希共同锁定。驱动或服务端在签发 Security Descriptor 时会依据这份授权清单仅放行匹配的包。在应用清单中声明自定义能力自定义能力通过uap4命名空间下的CustomCapability元素声明uap4 对应 Windows 10 版本 1703 及更高。以 JavaScript 版本清单 archived/CustomCapability/js/package.appxmanifest 为例其Capabilities节如下Capabilities rescap:Capability Namesmbios / !-- Enable protectedApp capability before store submission to access firmware variables in production environment -- !-- rescap:Capability NameprotectedApp / -- uap4:CustomCapability Namemicrosoft.firmwareRead_cw5n1h2txyewy / uap4:CustomCapability Namemicrosoft.hsaTestCustomCapability_q536wpkpf5cy2 / /Capabilities要点解读uap4:CustomCapability声明的能力名称必须与 SCCD 文件中CustomCapability Name...完全一致smbios与protectedApp是受限能力rescap命名空间。示例默认只启用了smbiosprotectedApp被注释掉——生产环境访问固件变量前需要取消注释并配合 INTEGRITYCHECK 触发商店对受保护应用的强制签名详见下文“固件访问”小节清单同时还注册了一个windows.backgroundTasks扩展Osrusbfx2Task.ConnectedTaskTask TypesystemEvent用于接收驱动在 OSR FX-2 设备接入时引发的自定义系统事件详见“自定义系统事件触发器”小节。C 版本的清单 Samples/CustomCapability/cpp/Package.appxmanifest 结构完全一致仅包名/Publisher 不同。场景一用自定义能力连接 NT 服务RPC这是示例中架构最完整的场景一个 UWP 客户端CustomCapability.exe通过 RPC 连接一个本地 NT 服务RpcServer.exe。为演示起见该服务从“虚拟设备”读取数据。通信流程原文档给出了如下时序图完整描述了 UI 操作与 RPC 调用的对应关系CLIENT SERVER ------------------------ ----------------- | | | | | CustomCapability.exe | | RpcServer.exe | | | | | ------------------------ ----------------- | | | | Click Start button |-------------StartMetering--------------| | [Blocking call] | | | | | Updates Sample |------------MeteringData----------------| text box | [Sent at choosen sample period] | | | | | Move the sample |-----------SetSamplePeriod--------------| period slider |-------SetSamplePeriod completes--------| | | Click Stop button |-------------StopMetering---------------| |--------StopMetering completes----------| | | |-------StartMetering completes----------| | |即点击Start发起阻塞式的StartMetering调用 → 服务按选定采样周期通过 RPC 回调MeteringData推送数据 → UI 文本框实时刷新拖动sample period 滑块调用SetSamplePeriod动态调整采样周期点击Stop调用StopMetering结束采集最后StartMetering返回完成。RPC 接口定义RPC 接口定义在 Samples/CustomCapability/Service/Interface/RpcInterface.Idl 中示例核心方法如下[uuid (F72945BF-CB3E-403E-B198-6149328304EF), // You must change this when you change the interface version(1.0), pointer_default(unique), ] interface RpcInterface { // context_handle_noserialize in acf for RPC to call rundown when the client goes away typedef [context_handle] void* PCONTEXT_HANDLE_TYPE; typedef [ref] PCONTEXT_HANDLE_TYPE * PPCONTEXT_HANDLE_TYPE; // // RPC methods to retrieve/clean client context // void RemoteOpen([in] handle_t hBinding, [out] PPCONTEXT_HANDLE_TYPE pphContext); void RemoteClose([in, out] PPCONTEXT_HANDLE_TYPE pphContext); // // Metering Interface // void StartMetering( [in] PCONTEXT_HANDLE_TYPE phContext, [in] __int64 samplePeriod, [in, optional] __int64 context); void SetSamplePeriod( [in] PCONTEXT_HANDLE_TYPE phContext, [in] __int64 samplePeriod); void StopMetering([in] PCONTEXT_HANDLE_TYPE phContext); [callback] void MeteringDataEvent( [in] __int64 data, [in, optional] __int64 context); }值得注意的实现细节PCONTEXT_HANDLE_TYPE是context handle上下文句柄配合.acf文件中的context_handle_noserialize可在客户端断开时触发 RPC run-down由服务端自动清理客户端上下文[callback]标注的MeteringDataEvent是反向回调——服务端主动向客户端推送计量数据该文件第 15 行的 uuid 是接口标识一旦修改接口定义必须同步更换新 uuid详见原文档“Modifying the sample”一节。服务端的安全模型由能力字符串派生 SID服务端Samples/CustomCapability/Service/Server 目录包含RpcServer.cpp、HsaService.cpp、Metering.cpp、ServiceInstaller.cpp等负责两件关键事使用DeriveCapabilitySidsFromName函数把能力字符串如microsoft.hsaTestCustomCapability_q536wpkpf5cy2转换为对应的SID用该 SID 创建 RPC 端点的Security Descriptor安全描述符。只有声明了该自定义能力且被 SCCD 授权的应用其进程令牌才携带对应的能力 SID才能通过 RPC 端点的 ACL 校验从而建立连接。这就是“自定义能力控制 NT 服务访问权”的本质。运行 NT 服务场景的前置条件在运行“Connect to an NT service”场景前必须先把服务跑起来先编译示例的服务端部分——该部分依赖Windows SDK for Desktop C Apps因此需要先安装对应桌面 C 开发组件以管理员权限打开命令行用下面两种方式之一启动服务作为系统服务安装并启动rpcserver.exe -install完成安装随后用sc start hsaservice启动服务名为hsaservice直接以控制台模式运行rpcserver.exe -console。场景二用自定义能力访问自定义设备OSR USB FX-2这一组场景演示如何用自定义能力访问OSR USB FX-2 Learning KitOSR 出品的 USB 学习板。设备驱动代码不在本仓库位于微软 Windows-driver-samples 仓库的usb/umdf2_fx2/driver目录驱动必须为Windows 10 1703 或更高版本构建才能支持示例使用的自定义能力驱动侧需通过 INF/代码把设备接口标记为受限并授权给对应的能力 SID。连接设备DeviceWatcher CustomDevice.FromIdAsync“Connect to the OSR FX-2 device”场景演示了四件事在清单中声明microsoft.hsaTestCustomCapability_q536wpkpf5cy2见上文清单更新驱动代码或 INF使设备接口通过自定义能力开放访问用DeviceWatcher按设备接口 GUID 枚举 OSR FX-2 设备用CustomDevice.FromIdAsync打开特定设备实例。从 C# 源码 Samples/CustomCapability/cs/DeviceList.cs 可以看到枚举器的构建方式先用CustomDevice.GetDeviceSelector(Fx2Driver.DeviceInterfaceGuid)构造基于接口 GUID 的 AQS 选择器再通过DeviceInformation.CreateWatcher创建DeviceWatcher并监听Added/Removed/EnumerationCompleted事件维护设备列表同时还会在应用挂起Suspending时停止 watcher、恢复Resuming时重启避免后台占用。JavaScript 版archived/CustomCapability/js/js/scenario2_deviceConnect.js展示了打开设备的调用方式var p Windows.Devices.Custom.CustomDevice.fromIdAsync( id, Windows.Devices.Custom.DeviceAccessMode.readWrite, Windows.Devices.Custom.DeviceSharingMode.exclusive );其中DeviceAccessMode.readWrite表示以读写方式打开DeviceSharingMode.exclusive表示独占共享模式。该文件的diagnoseConnectionError函数还总结了最常见的四种连接失败原因设备元数据未向任何应用授予自定义特权访问、设备元数据与应用包在应用名/发布者 ID 上不一致、设备接口未被驱动正确标记为受限、设备已断开。设备的接口 GUID 与 IOCTL 代码定义在 Samples/CustomCapability/cs/Fx2Driver.csC 对应 Samples/CustomCapability/cpp/Fx2Driver.hpublic static readonly Guid DeviceInterfaceGuid new Guid(573E8C73-0CB4-4471-A1BF-FAB26C31D384);发送 IOCTL读写 7 段 LED“Send IOCTLs to the device”场景演示向设备发送 I/O 控制码发送 IOCTL 设置 7 段 LED 的值SetSevenSegmentDisplay发送 IOCTL 读取 7 段 LED 的值GetSevenSegmentDisplay。I/O 控制码的值与含义由设备自身定义。从 Samples/CustomCapability/cs/Fx2Driver.cs 可以看到它们是用IOControlCode构造的public const ushort DeviceType 65500; public const ushort FunctionBase 0x800; public static IOControlCode SetSevenSegmentDisplay new IOControlCode(DeviceType, FunctionBase 8, IOControlAccessMode.Write, IOControlBufferingMethod.Buffered); public static IOControlCode GetSevenSegmentDisplay new IOControlCode(DeviceType, FunctionBase 7, IOControlAccessMode.Read, IOControlBufferingMethod.Buffered);IOControlCode的四个参数分别对应 CTL_CODE 的设备类型、功能号、访问模式Read/Write与缓冲方式Buffered 等文件里同时维护了 09 的七段数码管编码表SevenSegmentValues并提供DigitToSevenSegment/SevenSegmentToDigit双向换算。处理异步设备事件DIP 开关“Handle asynchronous device events”场景演示发送一个直到 DIP 开关发生变化才完成的 IOCTLGetInterruptMessage使用IOControlBufferingMethod.DirectOutput取消正在等待开关变化的任务发送 IOCTL 读取开关的当前状态ReadSwitches。操作方式点击“Begin Receiving Switch Change Events”后拨动 DIP 开关应用会在开关状态变化时显示当前状态也可以直接点击“Get Switch State”立即读取开关状态。这一模式展示了“设备中断型”异步事件如何在 UWP 中通过可取消的 I/O 任务实现。读写操作设备内部存储“Read and Write operations”场景演示向设备的OutputStream写入数据写入设备内部内存从设备的InputStream读取数据读取设备内部内存。每次点击“Write Block”会向设备写入一条消息点击“Read Block”则读取一条消息。OSR FX-2 内置4 个消息缓冲区缓冲区满时下一次写操作会阻塞等待直到有消息被读出腾出空间缓冲区空时下一次读操作会阻塞等待直到有消息写入。这一机制体现了流式接口基于缓冲区的背压backpressure语义。场景三触发自定义系统事件CustomSystemEventTrigger“Raising Custom System Event Trigger”场景演示如何使用CustomSystemEventTrigger类型的后台任务当 OSR FX-2 设备接入系统时由驱动侧抛出一个自定义系统事件进而触发应用注册的后台任务。事件触发代码位于 OSR FX-2 的 KMDF 驱动Windows-driver-samples 仓库usb/kmdf_fx2需为Windows 10 1803 或更高版本构建。这一机制的意义在于自定义设备/NT 服务可以主动向系统汇报事件从而唤醒 UWP 应用的后台任务而无需应用常驻或轮询。应用侧只需在清单中注册windows.backgroundTasks扩展本示例为Osrusbfx2Task.ConnectedTask并在代码里注册对应触发器类型的后台任务。场景四固件访问SMBIOS 与 UEFI 变量“Firmware access”场景演示通过受限能力与自定义能力访问固件声明受限能力smbios后应用即可读取 SMBIOS 信息——调用桌面 APIGetSystemFirmwareTable与EnumSystemFirmwareTables并以RSMBRaw SMBIOS作为表提供者provider参数访问 UEFI 变量则使用以下两个自定义能力microsoft.firmwareRead_cw5n1h2txyewy通过GetFirmwareEnvironmentVariable读取 UEFI 变量microsoft.firmwareWrite_cw5n1h2txyewy通过SetFirmwareEnvironmentVariable读写 UEFI 变量。原文档特别强调 UEFI 访问的三重额外前提应用还必须声明protectedApp受限能力项目需启用INTEGRITYCHECK链接选项强制签名校验这会在商店提交时为受保护应用触发必要的商店签名流程目前INTEGRITYCHECK 只能在 C 项目属性中启用UEFI 变量仅在应用由属于 Administrators 组的用户使用时才能访问。从 C 版本清单 Samples/CustomCapability/cpp/Package.appxmanifest 可以看到smbios已启用、protectedApp以注释形式保留便于开发者按上述流程自行开启。构建、部署与运行原文档给出的系统要求与构建步骤如下系统要求对应 JavaScript 归档版Client/Phone 为 Windows 10 version 1703Server 为 Windows Server 2016 Technical Preview活跃版本要求 Windows 10 build 15063 或更高Samples/CustomCapability/README.md并需 Visual Studio 构建、Windows 10 运行构建解压完整归档不要只解压单个示例文件夹→ 用 Visual Studio 打开对应语言的.slnJavaScript 归档版对应 archived/CustomCapability/js/CustomCapability.sln→ 按CtrlShiftB或选择Build Build Solution仅部署选择Build Deploy Solution部署并运行按F5或Debug Start Debugging调试运行按CtrlF5或Debug Start Without Debugging免调试运行运行“Connect to an NT service”场景前需先按上文步骤启动 NT 服务。修改示例的注意事项如果修改了 RPC 接口务必同步更换 Samples/CustomCapability/Service/Interface/RpcInterface.Idl 第 15 行的接口 ID因为 RPC 接口 ID 必须全局唯一产品化时还需要用正确签名的 SCCD 替换示例中的无效 SCCD。相关示例与延伸阅读原文档在 Related topics 中给出的关联示例活跃版本位于 Samples/CustomCapability/README.md 的 Related samples 一节同样围绕“自定义设备访问”主题IoT-GPIOIoT-I2CIoT-SPICustom HID device accessCustom serial device accessCustom USB device access此外JavaScript 归档版archived/CustomCapability与活跃版Samples/CustomCapability互为镜像前者保留在archived目录中以供查阅后者则持续维护并增加了 C/C# 实现。核心 API 是Windows.Devices.Custom.CustomDevice运行时类FromIdAsync、GetDeviceSelector、IOControlCode、InputStream/OutputStream等可结合官方“Custom Capabilities for Universal Windows Platform apps”与“Hardware access for Universal Windows Platform apps”文档进一步理解能力申请与硬件访问的整体流程。赞分享示例工程【免费下载链接】Windows-universal-samplesAPI samples for the Universal Windows Platform.项目地址https://gitcode.com/gh_mirrors/wi/Windows-universal-samples点击查看免费下载相关推荐Windows UWP 自定义 HID 设备访问全流程实战解读 Windows-universal-samples 的 CustomHidDeviceAccess 样例Windows UWP 自定义 HID 设备访问全流程实战解读 Windows universal samples 的 CustomHidDeviceAcce示例工程UWP 自定义媒体传输控件实战解析 Windows-universal-samples 的 XamlCustomMediaTransportControls 示例UWP 自定义媒体传输控件实战解析 Windows universal samples 的 XamlCustomMediaTransportControls示例工程UWP 标题栏定制实战基于 Windows-universal-samples TitleBar 示例的四种自定义方案UWP 标题栏定制实战基于 Windows universal samples TitleBar 示例的四种自定义方案 本指南以 Windows univer示例工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →