如何使用C++/WinRT通过Windows.Media.Control获取当前运行媒体会话信息
核心问题说明
你当前的代码无法运行的根本原因是:GlobalSystemMediaTransportControlsSessionManager 没有公开可直接调用的构造函数,不能像普通C++类一样直接栈上构造实例,必须通过类提供的静态异步方法RequestAsync()获取已初始化的管理器对象,之后才能调用GetSessions()枚举会话。
实现步骤
- 配置项目环境:确保项目已经正确引用对应版本Windows SDK的WinRT元数据,在代码文件中引入必要头文件
- 异步获取会话管理器实例:所有WinRT异步API必须在协程中通过
co_await调用,禁止同步阻塞等待避免死锁 - 枚举会话列表读取属性:拿到管理器实例后即可获取当前所有活跃媒体会话,遍历读取每个会话的应用标识、播放状态、媒体元数据等信息
- (可选)注册变更监听:如果需要实时感知会话启动/退出,可以注册
SessionsChanged事件自动刷新列表
可运行示例代码
#include <winrt/Windows.Media.Control.h> #include <winrt/Windows.Foundation.Collections.h> using namespace winrt::Windows::Media::Control; using namespace winrt::Windows::Foundation::Collections; // 协程函数,按需在你的业务逻辑中调用 winrt::Windows::Foundation::IAsyncAction LoadAllActiveMediaSessions() { // 异步获取初始化完成的会话管理器 GlobalSystemMediaTransportControlsSessionManager sessionManager = co_await GlobalSystemMediaTransportControlsSessionManager::RequestAsync(); // 拉取当前所有活跃媒体会话 IVectorView<GlobalSystemMediaTransportControlsSession> sessions = sessionManager.GetSessions(); // 遍历会话读取信息 for (auto const& session : sessions) { // 获取会话所属应用的AUMID,可用于映射应用名称 winrt::hstring sourceAppId = session.SourceAppUserModelId(); // 读取播放状态 GlobalSystemMediaTransportControlsSessionPlaybackInfo playbackInfo = session.GetPlaybackInfo(); auto playbackStatus = playbackInfo.PlaybackStatus(); // 读取当前播放媒体的元数据(标题、艺术家、专辑等) auto mediaProperties = co_await session.TryGetMediaPropertiesAsync(); if (mediaProperties) { winrt::hstring trackTitle = mediaProperties.Title(); winrt::hstring trackArtist = mediaProperties.Artist(); // 按需处理获取到的媒体信息 } } // 注册会话列表变更监听,会话新增/移除时自动触发 sessionManager.SessionsChanged([]( GlobalSystemMediaTransportControlsSessionManager const& sender, winrt::Windows::Foundation::IInspectable const& /*args*/) { // 重新拉取最新会话列表即可 IVectorView<GlobalSystemMediaTransportControlsSession> updatedSessions = sender.GetSessions(); // 处理更新后的列表 }); }
注意事项
- 线程要求:调用
RequestAsync()时需要当前线程为MTA(多线程单元),如果在UI线程(STA)调用,请确保C++/WinRT单元环境已正确初始化,否则会抛出调用失败异常。 - 空值处理:部分处于启动/退出过程中的会话,调用
TryGetMediaPropertiesAsync()可能返回空值,必须增加判空逻辑避免访问空指针崩溃。 - 权限说明:该API不需要额外在应用清单中声明特殊能力,但仅能枚举当前用户会话下的非受保护媒体进程,开启DRM保护的媒体应用可能无法读取完整元数据,仅能获取基础应用标识。
- 结果校验:调试时可以调出系统音量弹窗,弹窗中显示的活跃媒体会话就是该API能枚举到的全部会话,可直接对比校验结果是否正确。
学习建议
- 先掌握C++/WinRT协程的基本使用规则,所有名称以
Async结尾的WinRT API都需要通过co_await调用,不要尝试用get()等方法同步阻塞等待结果,极易造成UI线程死锁。 - 调试阶段先只读取
SourceAppUserModelId字段确认会话枚举正常,再逐步增加元数据读取、事件监听等逻辑,降低排错难度。 - 如果需要把AUMID转换为用户可读的应用名称,可以通过
PackageManager相关API根据AUMID查找应用对应的显示名。
内容的提问来源于stack exchange,提问作者MasiaSaig
相关产品推荐
相关产品推荐

