SENS:系统事件通知服务 和 WMI 支持灵活而有效的移动网络计算( 五 )


WMI 是对 WBEM 的实现 。设备驱动程序可以使用该服务向用户模式应用程序提供所有种类的数据 。WMI 提供了一种发现和获取数据的标准方式 。以这种方式公开的数据可以分为三个主要类别:信息、配置和通知 。我将重点讨论第三个类别 。
该数据到底是如何公开的?驱动程序定义包含数据项的 WMI 数据块 。数据块以托管对象格式 (MOF) 定义,并被编译为驱动程序的二进制文件的资源部分 。每个 WMI 数据块都由一个 GUID 唯一标识 。
当驱动程序初始化时,它的所有数据块都被注册到 WMI 。WMI 将已经注册的数据块添加到公共信息模型对象管理器 (CIMOM) 数据库中 。用户模式 WMI 客户端可以访问 CIMOM 中的数据块 。只有驱动程序和 WMI 客户端才知道各个数据块的格式 。WMI 将数据以透明方式从驱动程序传递到客户端 。客户端也可以有条件地注册事件 。
既然数据格式未知,客户端如何注册特定事件或某个事件的特定条件?答案可以在 WMI 查询语言 (WQL) 中找到 。WQL 基于 ANSI SQL 。
例如,要在计算机中启用了某个适配器时得到通知,可以使用下面的 WQL 语句:
SELECT * FROM MSNdis_NotifyAdapterArrival
这是一个事件查询 。WQL 还支持数据查询和架构查询 。数据查询用于检索类实例及其数据,而架构查询用于检索类定义和相关架构 。
事件查询可以使用 WHERE 子句进一步简化 。使用 WHERE,您可以告诉发布程序在某个类中的某个项取特定值时通知您 。考虑一下,每当网络连接的链接速度更改时,都会传递它 。WLAN 网络的一个典型特征是:随着两个同步节点之间的距离增加,数据速率会下降 。如果链接速度下降至某个固定速度以下,应用程序可能希望停止传输大型文件 。例如,您可以编写一个查询,使其在入站链接速度下降至 10KB 以下时通知您:
SELECT * FROM MSNdis_StatusLinkSpeedChange WHERE Inbound < 10000
您可以使用 OR 和 AND 运算符将多个子句组合起来 。您还可以使用 NOT 运算符;要进行比较,您可以使用 =、= 和 != 。有关其他选项,请参阅 WQL 文档资料 。
筛选查询始终是一个好主意 。记住,从发布程序到订户的调用最少要经过系统引入的一级间接寻址 。接收 WMI 通知的应用程序可以充当发布程序,并且判断您对您已经注册的某个事件的特定方面不感兴趣,从而避免向订户发送通知 。
返回页首
执行 WQL 查询
向 WMI 提交查询是通过 WMI 服务完成的,这些服务被以编程方式包装在接口中 。该接口的方法之一使用户可以使用 WQL 查询来注册异步事件通知:
HRESULT IWbemServices::ExecNotificationQueryAsync(const BSTR strQueryLanguage,const BSTR strQuery,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler);
是一个一般性接收器接口,可用于接收 WMI 通知 。通常情况下,您的接收器将把作为它的基类 。您将需要包括 DDK目录中的 .h 。6.0 随附的或SDK 中包含的 .h 不包含的定义 。链接器将需要包含 .lib 以解析该接口 。
在下面的代码中,我进行了一个调用,并且告诉它等待一个将注册所有适配器到达事件的 WQL 查询 。适配器到达事件被传递给对象:
HRESULT hr = m_ifpWbemServices->ExecNotificationQueryAsync((_bstr_t) _T("WQL"), bstrQuery, 0, 0, m_pWMISink);
m_pWMISink 对象的类型是 CWMISink,它继承自 IWbemObjectSink:class CWMISink : public IWbemObjectSink{...};
执行格式错误的查询时将返回值为的(ERY) 。执行带有错误类名的查询时将返回值为的() 。错误代码可以在 .H 中找到,该文件随附在 DDK 中 。如果您执行的查询带有永远不会被满足的条件,则您将不会得到任何错误 。WBEM 服务没有办法知道在运行时可能发生什么 。