VB使用WMI编程讲座(原版整理)(持续更新)

更新时间:2024-06-30 19:36:02 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

VB 使用WMI编程讲座(原创)

一、认识WMI

通常VB程序员经常抱怨VB在编制Windows系统软硬件设备控制方面的程序比较困难,即使能实现一些功能,那也是要通过调用繁复的API函数,即难找寻到合适的函数,又难以理解设置函数中的各项参数,尤其是调试异常困难,动不动整个程序连带VB环境一起死悄悄。此外,用API编程几乎完全抛弃了面向对象的编程方法,迫使我们回到过程方式的编程。那怎么办呢?^_^别急,微软在WIN2000系统中推出了VBScript脚本语言替代原来的批命令,同时提供了一个供VBScript管理Windows系统的对象WMI。那这个WMI对象我们VB能用吗?答案是肯定的,当然能用,而且用起来还非常方便,在网上也已经有了一些VB写的利用WMI实现Windows系统管理编程的例程,但却缺少系统性介绍使用VB对WMI编程的资料。本文就针对此问题,进行一个尝试。当然要学习WMI编程,需要有一定的VB基础,但要求不高,只要会用控件、对象,能理解和使用对象的方法、属性,但不需要任何API方面的知识和编程经验。

首先我们要知道什么是WMI?WMI是Windows Management Instrumentation (Windows管理工具)的缩写,是内置在 Windows 2000、Windows XP 和 Windows Server 2003 系列操作系统中核心的管理支持技术。基于由 Distributed Management Task Force (DMTF) 所监督的业界标准,WMI 是一种规范和基础结构,通过它可以访问、配置、管理和监视所有的 — 几乎所有的 Windows 资源。 呵呵,不要对这段文字进行咬文嚼字,通俗的讲,就是WMI是一个用于管理Windows系统的对象,就像ADO对象是用于数据库操作的。利用WMI我们可以管理Windows系统中的磁盘、事件日志、文件、文件夹、文件系统、网络组件、操作系统设置、性能数据、打印机、进程、注册表设置、安全性、服务、共享、用户、组等等。

而WMI适用的运得环境也是有些限制的, WMI 附带在 Windows Me、Windows 2000、Windows XP 和 Windows Server 2003 之中。对于 Windows 98 和 Windows NT 4.0,可以访问http://www.microsoft.com/downloads并搜索“Windows Management Instrumentation (WMI) CORE 1.5 (Windows 95/98/NT 4.

0)”。注意:在 Windows NT 4.0 上安装并运行 WMI 之前,需要首先安装 Service Pack 4 或更高版本。 WMI 需要的其他软件包括:

1. Microsoft Internet Explorer 5.0 或更高版本。

2. Windows Script Host(WSH)。Windows 2000、Windows XP、Windows Server 2003、和 Windows Me 附带的 WSH,而不是 Windows NT4 或 Windows 98 附带的 WSH。您可以从以下地址下载 WSH http://www.microsoft.com/downloads. WSH 的最新版本—— 包括在 Windows XP 和 Windows Server 2003 之中——是 WSH 5.6。

要使WMI脚本可以正常的运行,Windows里的WMI 服务(winmgmt)保证是运行的,这样才可以实现WMI里的更多功能。好了,关于WMI的一些基本的信息资料就说到这,要想看更多的可以到MicroSoft网站的MSDN找。

大家都喜欢通过例程来学东西,那我们也先编一段程序来看看。不知道大家看到过没有本人在本论坛中曾经写过一篇“自己做进程管理器”的帖子,在那篇帖子里主要是采用API函数罗列出当前系统下正在运行的所有进程,下面我们利用WMI也来做一个进程管理器。首先建立一个新工程具有Form1窗体,在菜单中的【工程】—【部件】下,添加“Microsoft Windows Common Controls 6.0”,在菜单中的【工程】—【引用】下,添加“Microsoft WMI Scripting V1.1 Library”,然后在Form1窗体上添加1个ListView1和Command1、Command2,在代码窗口添加如下代码(例程1):

Option Explicit

Dim objSWbemLocator As New SWbemLocator Dim objSWbemServices As SWbemServices Dim objSWbemObjectSet As SWbemObjectSet Dim objSWbemObject As SWbemObject

Private Sub Form_Load()

Me.Caption = \进程管理器\ Command1.Caption = \刷新\ Command2.Caption = \结束进程\ ListView1.ColumnHeaders.Clear

ListView1.ColumnHeaders.Add , \进程ID\ ListView1.ColumnHeaders.Add , \进程名\ ListView1.ColumnHeaders.Add , \路径\ ListView1.View = lvwReport Command1_Click '刷新进程列表 End Sub

Private Sub Command1_Click() Dim i As Long

ListView1.ListItems.Clear '清空ListView

Set objSWbemServices = objSWbemLocator.ConnectServer() '连接到本机的WMI,返回一个对 SWbemServices 对象的引用

Set objSWbemObjectSet = objSWbemServices.InstancesOf(\ss\返回Win32_Process类名标识的所有实例 i = 0

For Each objSWbemObject In objSWbemObjectSet '枚举每一个Win32_Process的实例

ListView1.ListItems.Add , \将进程ID添加到ListView1第一列

ListView1.ListItems(\e '将进程名添加到ListView1第二列

If Not IsNull(objSWbemObject.ExecutablePath) Then _

ListView1.ListItems(\ExecutablePath '将进程路径添加到ListView1第三列 i = i + 1

Next

Set objSWbemObjectSet = Nothing End Sub

Private Sub Command2_Click() Dim TMBack As Long

If ListView1.SelectedItem.Text <> \

If MsgBox(\确实要结束进程[\(1) & \吗?\

Set objSWbemObjectSet = objSWbemServices.ExecQuery(\T * FROM Win32_Process WHERE Handle = '\t & \查询Win32_Process类中Handle属性等于指定值的所有实例 For Each objSWbemObject In objSWbemObjectSet

TMBack = objSWbemObject.Terminate '终止指定进程 Next

If TMBack = 0 Then

MsgBox ListView1.SelectedItem.SubItems(1) & \已经被终止!\

Else

MsgBox ListView1.SelectedItem.SubItems(1) & \不能被终止!\

End If

Command1_Click '刷新进程列表 End If End If End Sub

呵呵,我们没有用任何系统的API函数却千真万确的实现了进程管理这个系

统级的应用,而且采用的是标准的面向对象的编程,其实这段代码仅仅实现了我们在前面提到的一篇“自己做进程管理器”的帖子中用API函数也能实现的功能。嗯???怎么?还能比这更强?哈哈,当然!!下一讲我们分析该例程时,还会告诉各位,将该例程稍加修改,就可以在你的局域网中对任何一台WIN2000以上的计算机进行进程管理!晕!那不是我就能在我的局域网中为所欲为了吗?别急,那当然是有条件的,微软当然不会允许未经授权就可以随便控制其它的计算机的。

因为本人平时工作还是比较忙的,只有抽空就继续写,打算每星期写一讲,本次算是第一讲,下一讲主要结合本讲的例程,介绍在VB中使用WMI的基本方法。

二、VB中使用WMI的基本方法

上一讲我们初步了解了一下WMI,并在VB中使用WMI对象做了一个进程管理器,为加深各位的对WMI对象引用方法的程序结构印象和增加兴趣,我们再举一个例子,就是枚举当前系统所有服务的名称、状态和启动类型等。与例程1一样,首先建立一个新工程具有Form1窗体,在菜单中的【工程】—【部件】下,添加“Microsoft Windows Common Controls 6.0”,在菜单中的【工程】—【引用】下,添加“Microsoft WMI Scripting V1.1 Library”,然后在Form1窗体上添加1个ListView1,在代码窗口添加如下代码(例程2):

Option Explicit

Dim objSWbemLocator As SWbemLocator Dim objSWbemServices As SWbemServices Dim objSWbemObjectSet As SWbemObjectSet Dim objSWbemObject As SWbemObject

Dim strComputer As String, strNameSpace As String, strClass As String

Private Sub Form_Load() Dim i As Long

Me.Caption = \服务\

ListView1.ColumnHeaders.Clear

ListView1.ColumnHeaders.Add , , \名称\ ListView1.ColumnHeaders.Add , , \状态\ ListView1.ColumnHeaders.Add , , \启动类型\ ListView1.ColumnHeaders.Add , , \路径\ ListView1.ColumnHeaders.Add , , \登录身份\ ListView1.View = lvwReport

strComputer = \计算机名,.为本机 strNameSpace = \指定命名空间为root\\cimv2 strClass = \指定类为Win32_Service

Set objSWbemLocator = CreateObject(\ '建立1个WBEM对象的引用指针

Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, strNameSpace) '连接到指定计算机、命名空间的WMI,返回一个对 SWbemServices 对象的引用

Set objSWbemObjectSet = objSWbemServices.ExecQuery(\ \通过WQL查询,返回指定类的所有实例

For Each objSWbemObject In objSWbemObjectSet

ListView1.ListItems.Add , \ '将服务名称添加到ListView1第一列

ListView1.ListItems(\te '将服务的状态添加到ListView1第二列

ListView1.ListItems(\rtMode '将服务的启动方式添加到ListView1第三列

ListView1.ListItems(\

hName '将服务程序的路径添加到ListView1第四列

ListView1.ListItems(\rtName '将服务的登录身份添加到ListView1第五列 i = i + 1 Next

Set objSWbemObject = Nothing Set objSWbemObjectSet = Nothing End Sub

嘿,我们运行这个例程后,果然把自己计算机上所有的服务都列了出来,并且还知道这些服务目前的运行状态以及服务程序所在的目录和执行文件名。美中不足的是似乎我们不能停止或启动某个服务,不要急,其实可以很方便的就增加停止或启动某个服务的功能,但因为本节主要是要讨论VB中使用WMI的基本方法,因此故意省略了其它一些功能的实现。

闲话少说言规正传,现在我们就开始讨论一下VB中使用WMI的基本方法。例程2与例程1相比,除了功能不一样外,精简了程序结构,因此我们就以例程2的结构为主进行讨论。

我们先来观察一下例程1和例程2,可以看到它们都添加了“Microsoft WMI Scripting V1.1 Library”的引用,这个对象库(以下简称WMI脚本对象库)就是我们在VB的WMI编程中所要依赖的。再看一下程序的定义部分和整个程序的首次执行过程,它们基本相同:都定义了SwbemLocator、SwbemServices、SwbemObjectSet、SwbemObject对象;创建了SwbemLocator指针实例;通过SwbemLocator指针连接到WMI服务;检索一个 WMI 托管资源;枚举托管资源中的每个实例;显示各实例的一些属性。其实这些步骤对于任何用于检索 WMI 托管资源信息的程序来说都是共同的,下面我们就详细的分析一下各步骤。 1)创建SwbemLocator指针

创建SwbemLocator指针的目的是为了建立一个引用WMI对象的实例,然后用这个实例操作WMI。有没有注意到,例程1和例程2创建SwbemLocator指针稍有不同,例程1是在定义处用Dim objSWbemLocator As New SwbemLocator

定义语句直接创建了,而例程2是在执行过程Form_Load中用Set objSWbemLocator = CreateObject(\语句创建的,其实可以将这条语句简化为Set objSWbemLocator = New SwbemLocator来创建。不管用哪种方式创建SwbemLocator指针,都不影响下面的步骤。SwbemLocator指针对象只有1个只读属性Security_(其实也是一个对象)和1个方法ConnectServer,第二步中我们就会讨论用此方法连接到WMI服务。 2)连接到WMI服务

要用WMI对象编程,必须连接到目标计算机的WMI服务,然后返回一个SwbemServices对象。比较一下例程1和例程2的连接方法,它们都用SwbemLocator指针对象的ConnectServer方法实现,不过例程1没有用任何参数,例程2中增加了strComputer和strNameSpace二个参数。ConnectServer方法共有8个参数,所有参数都是可选的,因此我们看到例程1中没有用任何参数,即全部使用缺省参数。下面我们看一下这8个参数:

strServer 计算机名字,如果这台远程计算机与你不是同一个主域,需要完整的带域名的全称,例如:”cp1.xxxx.yyy”。缺省为本机,本机也可以用”.” strNamespace 需要登录的CIM命名空间,例如:\。缺省为\oot\\CIMV2\。(CIM就是一个存储库(架构),包括模型化托管环境和定义每个由 WMI 公开的数据块的对象储存库或类存储,WMI所有的类被分组到命名空间中,命名空间是表示一个特定的管理区域的类逻辑组,在这里就不深入分析了) strUser 用户名,一般必须为指定计算机上管理员帐号,也可以是指定主域的用户名,例如:\。缺省为当前登录系统帐号的用户名。 strPassword 口令(密码),对应用户名的口令 strLocale 本地化代码,通常为空。

StrAuthority 验证字符串,通常为空,如果不为空,则只能用于“Kerberos”或“NTLMDomain”。

iSecurityFlags 延迟时间(注:中文解释为本人理解,似乎和英文意思不一样),当为0时,直到连接成功为止,这就有可能因为连接不成功时长时间等待。当为wbemConnectFlagUseMaxWait (数值为128),则确保不超过2分钟返回。

ObjwbemNamedValueSet 为wbemNamedValueSet对象,在这里就不展开了。 如果连接到本机,通常情况下只需要设置strNamespace参数,其它参数都可以省略,但如果连接到远程计算机,一般需要对前4个参数进行设置。 这里要注意的是,连接到WMI服务是指连接到一个指定的CIM命名空间(如果还不能理解什么是CIM命名空间,也没关系,在后面的章节中还会讨论CIM命名空间),所以也可以认为本步骤就是:连接到一个指定的CIM命名空间,即使你不设置strNamespace参数,那也是连接到缺省的CIM命名空间,通常缺省的CIM命名空间为\,你可以通过你计算机上的注册表查看或修改HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\WBEM\\Scripting\\Default Namespace项的值。

3)获得WMI 托管资源(类)的实例集合

当完成了连接到WMI服务后,我们就需要根据要执行的任务,选择不同的类(这些类都是WMI 的托管资源)。在上一步中,我们已经知道是连接到一个指定的CIM命名空间,而每个命名空间都驻留了许多类,本步骤就是根据要求获得我们所需类的实例集合。

我们还是通过例程来讨论。在例程1中,我们通过SwbemServices对象的InstancesOf方法,参数为我们所需的\类,然后返回由指定类名标识(\的托管资源的所有实例。而在实例2中,我们通过SwbemServices对象的ExecQuery方法,参数为\(细心的读者可能发现参数好像与例程2中的并不完全相同,但你再看一下该语句执行前,已经对strClass变量赋予了\值),然后返回的却是由指定类名标识(\的托管资源的所有实例。2个例程用了2个方法都获得指定类名标识的托管资源的所有实例,那可不可以调换过来用呢?当然可以! 在例程1中,我们完全可以用Set objSWbemObjectSet = objSWbemServices.ExecQuery(\替换原语句,在例程2中用Set objSWbemObjectSet = objSWbemServices.InstancesOf(\ice \替换原语句。既然可以互相替换,那是不是说这2种方法是一样的呢?实际上这2种方法是有区别的。InstancesOf方法就象其名字所体现的一样,返回所有指定类实例,所以用起来非常方便。但方便往往与灵活和高效是矛盾的,假

设您只想要实例或属性的一个子集的情形又怎么样呢?假设您想要优化实例和属性恢复到最小的网络流量。在这种情况下,您会非常高兴听到 WMI 支持大量强大的查询工具。

查询 WMI 是向匹配一些预定义条件的托管资源发出请求的过程。例如,WMI 查询只要求那些处于 Stopped(停止)状态的服务,则例程2中,我们可以将该条语句改成:Set objSWbemObjectSet = objSWbemServices.ExecQuery(\ECT * FROM Win32_Service WHERE State='Stopped'\就可以了。

WMI 查询为检索托管资源实例及其属性提供了比 InstancesOf 方法更有效率的机制。WMI 查询只返回那些匹配查询的实例和属性,但是 InstancesOf 总是返回一个指定资源的所有实例以及每个实例的所有属性。同样,查询是在与对象路径中一致的目标计算机上进行的,而不是在运行的源计算机上。因此,WMI 查询可以显著地减少像 InstancesOf 那样更低效率的数据检索机制造成的网络流量。

要查询 WMI,使用 WMI 查询语言(WQL)构造一个查询字符串。查询字符串定义了必须被满足的条件来获得成功匹配的结果。在查询字符串定义后,查询使用 SWbemServicesExecQuery 方法提交到 WMI 服务。满足查询的托管资源实例以 SWbemObjectSet 集合的形式返回。

使用 WQL 和 ExecQuery 方法(而不是 InstancesOf)为创建只返回您感兴趣的项提供了灵活性。但我目前尚未获得一个完整的关于WQL查询语言的资料,只知道“WQL查询语言是一种类似于SQL查询语言,是SQL语言的一个子集”,但我在实际使用时,发现并不完全是SQL语言的一个子集,WQL语言还能用于建立事件,控制事件的响应速度等,不知道是否因为本人孤陋寡闻,在SQL中是不是有WITHIN、ISA等关键字?那位如有完整的关于WQL查询语言的资料(最好是电子的)能够提供,本人不胜感谢!

好,讨论过了获得实例集合的方法,我们是不是还有一个疑问?参数中的\Win32_Process\和\是什么?这些就是我们称作托管资源的类,大约有数千个不同的类,通常分为系统类、核心与公共类以及扩展类,我们作为应用人员角度,所关心的主要是扩展类,它们通常都在root\\cimv2 命名空间中,大部分是一些以Win32_开头命名的类,大约有4、5百个。这些类可以通过微软

本文来源:https://www.bwwdw.com/article/m3u3.html

Top