WMI Scripting Primer: Part 3
WMI脚本入门 3
Greg Stemp, Dean Tsaltas, and Bob Wells
Microsoft Corporation
Ethan Wilansky
Network Design Group
January 23, 2003
Summary: Defines the WMI scripting library and shows how to use it to access and manage WMI managed resources. Walks through the seven basic script types that can be created using the WMI scripting library for such tasks as creating, deleting, and retrieving instances of managed resources, and more. (22 printed pages)
讲述了WMI的参考库和如何使用它来访问和管理WMI托管资源,可以从参考库中使用的七种基本的脚本类型。比如:创建、删除、获取托管资源的实例等等
Greetings fellow script scribes! It's been awhile. Rather than bore you with excuses—like we were finishing the Microsoft® Windows® 2000 Scripting Guide (more on that later)—let's dive in, shall we? We're going to pick up where we left off in our WMI Scripting Primer series by turning your attention to the remaining piece of the WMI scripting puzzle, the WMI Scripting Library.
Before we get too far along, let's briefly recap what we've covered so far. In WMI Scripting Primer: Part 1, we covered the architecture and major components of WMI as they relate to WMI scripting. In WMI Scripting Primer: Part 2, we talked about the Common Information Model, the repository that holds the blueprints (class definitions) for WMI managed resources. Although we know many of you skipped Part 2 (based on the number of "Rate this page" hits), we're still going to assume you know the material. If you don't, well, you know where to find it.
在继续进行之前,我们先简单的回忆一下学过的东西。在第一部分中我们讲了与WMI脚本相关的体系结构和WMI的主要组件;第二部分中讲了CIM(通用信息模型),包含有类定义的仓库。虽然很多人跳过了第二部分,我还是假设你已经了解了相关的材料。如果没有,好吧,你知道在那里能找到。
WMI Scripting Library Defined
So, just what is the WMI scripting library? Let's use an analogy to answer that question. Think about your stereo system or the media player on your computer for a moment. What do all stereos have in common? Well, they all have a volume control, treble and bass controls, a tuner in the case of a radio, and perhaps an equalizer. And it doesn't matter whether you choose to listen to Beethoven, Led Zeppelin, Art of Noise, or whoever; the controls always work the same.
WMI脚本库的定义
那么,什么是WMI的脚本库呢?我使用一个比喻来回答这个问题,想一下你的立体声音响或计算机上的媒体播放器。所有的立体声都有什么相同的地方呢?对,他们都有音量控制、颤音和低音控制、频率调节(如果有收音机的话),可能还有一个均衡器。而且不管你在那里听贝多芬、Led Zeppelin、Art of Noise,这些控制器的作用都是一样的。
The WMI scripting library is like—not really, but humor us—the controls on your stereo. That is, the WMI scripting library provides a consistent set of controls (in the form of automation objects) that allow you to access and manage WMI managed resources. It doesn't matter whether you're managing computers, event logs, the operating system, processes, services, or pick your favorite resource; the objects in the WMI scripting library always work the same.
WMI的脚本库就像是(并不完全是)你的立体声上的控制器。就是说WMI脚本库提供了一系列的控制器(以Automation Object的形式)可以用来访问和管理WMI托管资源,而不管托管对象是计算机、事件日志、操作系统、进程、服务或用户选择的资源,WMI脚本库中的对象都进行相同的工作。
The consistency provided by the automation objects in the WMI scripting library is best conveyed by the finite set of tasks you can perform using the WMI scripting library. All told, you can create seven basic script types using the WMI scripting library.
在WMI脚本库的功能范围内,使用Automation Object来完成这些任务是最合适不过的。下面列出了WMI脚本库可以完成的七种基本的任务。
- You can retrieve instances of WMI managed resources.
- You can read the properties of a WMI managed resource.
- You can modify the properties of a WMI managed resource.
- You can call a method of a WMI managed resource.
- You can create a new instance of a WMI managed resource.
- You can delete an instance of a WMI managed resource.
- You can subscribe to events to monitor the creation, modification, and/or deletion of a WMI managed resource.
1.可以获取WMI托管资源的实例
2.可以读取WMI托管资源的属性
3.可以修改WMI托管资源的属性
4.可以调用WMI托管资源的方法
5.可以在WMI托管资源中创建一个新的实例
6.可以在WMI托管资源中删除一个实例
7.可以订阅下列事件:对WMI托管资源的创建、修改、删除
You can think of the seven basic script types as script templates. And just like the volume control adjusts the loudness of any CD, cassette, 8-track tape, or .wma file, the WMI script templates can be used to manage any WMI managed resource. Once you understand a template well enough to manage one type of WMI managed resource, you can easily adapt the same template to manage hundreds of other WMI managed resources.
也可以把这七种脚本类型看作是模板。就像音量调节器来控制CD、录音机或是.wma的音量一样,WMI脚本模板可以用来管理任何WMI的托管资源。主要学会了如何使用这些模板来管理一种托管资源,就可以很轻松的适应对其他上千中WMI资源的管理。
WMI Scripting Library Object Model
Now that we've established the WMI scripting library is your control panel to the entire WMI infrastructure, let's open the chassis and look inside. Figure 1 in Part 1 of this series showed you that the WMI scripting library is implemented in a single automation component named wbemdisp.dll that physically resides in the %SystemRoot%\system32\wbem directory.
WMI脚本库对象模型
我们已经确定WMI脚本库是整个WMI体系结构的控制面板,现在来打开看看里面有什么。这个系列讲座第一部分的图一已经说明WMI脚本库是应用在一个单个的Automation组件wbemdisp.dll, 存储在%SystemRoot%\system32\wbem目录下。
All told, the WMI scripting library consists of twenty-four automation objects (nineteen in Windows 2000 and earlier), twenty-one of which are illustrated in the WMI scripting library object model diagram shown in Figure 1. Now, before you go into meltdown thinking you must learn the gory details of all twenty-four objects, let us politely point out that you do not. In fact, you'll be happy to learn you can create 6 of the 7 script templates listed earlier with a basic understanding of just two or three of the objects shown in Figure 1. What are those objects? Sit tight, you're getting ahead of us.
已经说过,WMI脚本库包含有24个Automaion Object(Windows2000和较早版本为19个),其中的21个已在图一中列出。在深入学习之前,你必须学完所有24个对象的令人胆战心惊的细节内容。现在我们只能礼貌的指出:你还没有学完。实际上在粗略了解了图一中的2到3个对象后,你就很高兴得发现自己已经可以写出6、7个脚本了。耐心一点,你超过了我们的进度。
In addition to the twenty-four automation objects in the Microsoft Windows XP and Windows Server 2003 version of wbemdisp.dll, the scripting library also contains thirteen enumerations. Enumeration is just a fancy name for a group of related constants. We're not going to cover the groups of constants here, because they're covered quite well in the WMI SDK. To learn more about the WMI scripting constants, see Scripting API Constants in the WMI SDK.
出了XP和2003版本的wbemdisp.dll中的24个Automation Object,脚本库中还有13个枚举。枚举只是一组相关实例的一个特定的名称。我们并不打算在这里讲述那些实例组,因为在WMI的SDK中讲的很明白。
In many ways, you can compare the automation objects in the WMI scripting library to the core interfaces provided by ADSI. What do we mean by that? Well, the ADSI core interfaces—IADs and IADsContainer, for example—provide a consistent approach to scripting objects in the Active Directory, irrespective of an object's class and attributes. Similarly, the automation objects in the WMI scripting library provide a consistent and uniform scripting model for WMI managed resources.
在很多方面,可以将WMI脚本库中的Automation Object和ASDI提供的核心借口相比较。什么意思呢?ASDI的核心接口-IADs和IADsContainer,例如-对目录提供了统一的编程途径,而不用理会对象的类和属性。和这个类似,WMI脚本库中的Automation Object对WMI的托管资源提供了统一的编程模型。
It's important to understand the relationship between the automation objects in the WMI scripting library (wbemdisp.dll) and the managed resource class definitions that reside in the CIM repository (objects.data). As we explained in Part 2, managed resource class definitions are the blueprints for the computer resources exposed through WMI. In addition to defining the resources that can be managed, the blueprints define the methods and properties unique to each managed resource.
正确理解Automation Object(WMI脚本库中的)和CIM库中的托管资源类的定义这两者之间的关系是很重要的。就是我们在第二部分中讲的管资源类的定义是通过WMI所暴露的计算机资源的蓝图。对于要定义的托管资源,蓝图定义出了其唯一的方法和属性。
The WMI scripting library, on the other hand, provides the general purpose set of automation objects scripts used to authenticate and connect to WMI, and subsequently access instances of WMI managed resources. Once you obtain an instance of a WMI managed resource using the WMI scripting library, you can access the methods and properties defined by the managed resource's class definition—as if the methods and properties were part of the scripting library itself.
另一方面来说,WMI脚本库提供了用于连接、身份验证以及随后队托管资源德实例进行访问的Automation Object脚本。一旦使用WMI脚本库获得了托管资源的一个实例,用户就可以访问到托管资源类所定义的方法和属性,就像这些方法和属性是脚本库本身的一部分一样。
Figure 1. WMI scripting library object model, wbemdisp.dll
图一 WMI脚本库对象模型 wbemdisp.dll
Interpreting the WMI Scripting Library Object Model
Although Figure 1 may not appear very intuitive at first glance, the WMI scripting library object model provides a great deal of insight into the mechanics of how WMI scripting works. The lines in Figure 1 point to the object that is obtained by calling a method (or accessing a property) of the originating object. For example, calling the SWbemLocator ConnectServer method returns a SWbemServices object. Calling the SWbemServices ExecNotificationQuery method returns a SWbemEventSource object. On the other hand, calling the SWbemServices ExecQuery or InstancesOf method returns a SWbemObjectSet collection. And calling the SWbemServices Get method returns a SWbemObject.
对脚本库对象模型的解释
虽然图一第一眼看上去并不是很清楚,但是WMI脚本库对象模型提供了关于WMI脚本工作机制的的深入说明。图一中线指向的对象是通过调用一个对象的方法(或访问一个属性)所获得的。例如调用SWbemLocator的ConnectServer方法可以返回一个SWbemServices对象,调用SWbemServices ExecNotificationQuery方法返回一个SWbemEventSource对象,另一方面调用SWbemServices ExecQuery或InstancesOf方法返回一个SWbemObjectSet的集合,调用SWbemServices Get方法返回一个SWbemObject
Let's compare the WMI scripts presented in Part 1 and Part 2 of this series to the object model to see how they worked.
我们来对比一下Part1和Part2的脚本来看他们是怎样工作的
Each script performed three basic steps common to many WMI scripts.
每一个脚本都执行了三个基本的步骤(对于许多WMI脚本都是如此)
- Each script started by connecting to the WMI service on a target computer. The scripts used the Microsoft® Visual Basic® Scripting Edition (VBScript) GetObject function combined with a WMI connection string consisting of the WMI moniker, "winmgmts:", followed by a WMI object path to the target computer and namespace.
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Connecting to WMI in this way returns a reference to the SWbemServices object shown in Figure 1. Once you obtain a reference to a SWbemServices object, you can call one of SwbemServices methods. The SWbemServices method you call largely depends on the type of WMI script you're creating.
每个脚本都以连接到目标机器上的WMI服务为开始。脚本使用了VBScript的GetObject,组合了WMI的连接字符串(Moniker, winmgmts:),以及WMI对象在目标机器和命名空间的路径。
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
这样连接到WMI返回一个图一中SWbemServices对象的参考。当获得了对SWbemServices的连接之后,就可以调用SwbemServices中的方法,具体调用那些方法基于你所写的脚本。
- Next, each script retrieved instances of a WMI managed resource using the SWbemServices InstancesOf method.
Set colSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Service")
InstancesOf always returns a SWbemObjectSet collection. As shown by the line between the SWbemServices and SWbemObjectSet objects in Figure 1, SWbemObjectSet is one of the three WMI scripting library object types SWbemServices can return.
接下来,每一个脚本都使用了SWbemServices InstancesOf方法来获得托管资源的实例,
Set colSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Service")
InstancesOf 总是返回一个SWbemObjectSet的集合,在图中SWbemServices和SWbemObjectSet对象之间的连线可以看到,SWbemObjectSet是SWbemServices可以返回的WMI脚本资源库中三种对象之一。
- Finally, each script accessed properties of a WMI managed resource by enumerating the instances in the SWbemObjectSet.
For Each objSWbemObject In colSWbemObjectSet
WScript.Echo "Name: " & objSWbemObject.Name
Next
As illustrated in Figure 1, each managed resource instance in a SWbemObjectSet collection is represented by a SWbemObject.
最后,每一个脚本都通过枚举SWbemObjectSet中的实例访问了WMI托管资源的属性
For Each objSWbemObject In colSWbemObjectSet
WScript.Echo "Name: " & objSWbemObject.Name
Next
按照图一所描述的,SWbemObjectSet中的每一个托管实例集合都是以SWbemObject的形式存在。
Of the twenty-four automation objects in the WMI scripting library, the three most important—that is, the three you should learn first—are SWbemServices, SWbemObjectSet, and SWbemObject. Why? Because SWbemServices, SWbemObjectSet, and SWbemObject are an essential part of darn near every WMI script. In fact, if we revisit our ADSI analogy, SWbemServices, SWbemObjectSet, and SWbemObject are to WMI scripting what IADs and IADsContainer are to ADSI scripting. (Scripting Guys Freebie: There's a tip in there for those of you that haven't dabbled in ADSI scripting.—.That is, of the sixty interfaces provided by the ADSI library, IADs and IADsContainer are the two you should learn first. Trust us.)
在所有的24个Automation Object中最重要的三个(也是最先学到的)是SWbemServices, SWbemObjectSet和SWbemObject。因为这三个是几乎每个WMI脚本中的必用的部分。实际上我们再回头看ADSI,SWbemServices, SWbemObjectSet和SWbemObject对于WMI就如同IADs和IADsContainer对于ADSI脚本编程一样。
SWbemServices is the object that represents an authenticated connection to a WMI namespace on a local or remote computer. Additionally, SWBemServices plays an important role in every WMI script. For example, you use the SWbemServices InstancesOf method to retrieve all instances of a managed resource. Similarly, you use the SWbemServices ExecQuery method combined with a WQL (WMI Query Language) query to retrieve all or a subset of instances of a managed resource. And you use the SWbemServices ExecNotificationQuery method to subscribe to events that represent changes in the managed environment.
SWbemServices是用于对连接到本地或远程计算机的WMI命名空间进行身份验证的对象。而且在每一个WMI脚本中,SWBemServices都是一个很重要的角色。例如你可以使用SWbemServices InstancesOf方法来获取托管资源的所有的实例。类似的情况,你也可以使用SWbemServices Execquery方法结合一个WQL查询来获取托管资源所有或部分实例。而且可以使用SWbemServices ExecNotificationQuery方法来订阅事件以及时知道托管环境中的变化。
A SWbemObjectSet is a collection of zero or more SWbemObject objects. Why zero? Because it's possible for a computer to have zero instances of, say, a tape drive (modeled by Win32_TapeDrive). Each SWbemObject in a SWbemObjectSet can represent one of two things:
- An instance of a WMI managed resource.
- An instance of a class definition.
SWbemObjectSet是一个或多个SwbemObject对象的集合。为什么会有0个呢?因为有的计算机可能一个实例也没有,比如磁带驱动器(Win32_TapeDrive模块)。SWbemObjectSet中的每一个SWbemObject都表示下列之一:
- 一个WMI托管资源的实例
- 一个类定义的实例
SWbemObject is the multiple-identity object that masquerades as the resource you're managing. For example, if you retrieve instances of the Win32_Process managed resource, SWbemObject takes on an identity modeled after the Win32_Process class definition, as shown on the left of Figure 2. On the other hand, if you retrieve instances of the Win32_Service managed resource, SWbemObject takes on an identity modeled after the Win32_Service class, as shown on the right of Figure 2.
SWbemObject是一个多实体的对象,可以看作是正被进行管理的资源。例如从Win32_Process中获取实例时,SWbemObject就表现为Win32_process中的一个实例,如图二。另一方面来说,如果从Win32_Servcie中获取实例,SWbemObject就会表现为Win32_service中的实体。
Figure 2. SWbemObject masquerading as a Win32_Process and Win32_Service
图二,SWbemObject以Win32_Process和Win32_Service实体的形式出现
If you examine Figure 2 closely, you'll notice SWbemObject exposes two distinct sets of methods and properties. The top set with the names that end with an underscore are part of SWbemObject and live in wbemdisp.dll. The underscores are used to prevent name collisions with methods and properties defined by a managed resource's class definition.
如果你仔细的查看图二的话,你就会发现SWbemObject暴露出了两套不同的方法和属性。上面的一套以下划线为后缀的是SWbemObject中的一部分,位于wbemdisp.dll,下划线是用来和托管资源类定义的方法和属性相区分的。
The bottom set of methods and properties are not part of SWbemObject. They are defined by a managed resource's class definition in the CIM. When you retrieve an instance or instances of a managed resource, SWbemObject dynamically binds to the methods and properties defined by the managed resource's class definition. You use SWbemObject to call the methods and access the properties defined in the managed resource's class definition as if the methods and properties were part of SWbemObject. The ability of SWBemObject to morph into any managed resource defined in the CIM is what makes WMI scripting so intuitive. Once you know how to connect and retrieve instances, everything is a SWbemObject.
下面的一套方法和属性就不是SWbemObject中的了,它们都是由CIM中的托管资源的类定义的。当从托管资源中获取实例时,SWbemObject动态地绑定托管资源的类定义的方法和属性,然后就可以使用SWbemObject来调用,就像这些方法和属性是SWbemObject的一样。就是SWBemObject能够将CIM中的托管资源绑定到自身,才使得WMI的脚本编程变得如此简单。
OK. So what else does the WMI scripting library object model tell you? The object model tells you SWbemServices and SWbemObject can be directly created using the VBScript (or WSH) GetObject function combined with the WMI moniker (winmgmts:) and a WMI object path (for example, "[\\ComputerName][\Namespace][:ClassName][.KeyProperty='Value']"). On the other hand, SWbemLocator, SWbemLastError, SWbemObjectPath, SWbemNamedValueSet, SWbemSink, SWbemDateTime, and SWbemRefresher objects are created using the VBScript (or WSH) CreateObject function. The remaining objects cannot be created using GetObject or CreateObject. Instead, they are obtained by calling a method or accessing a property.
好的,WMI脚本库的对象模型还使我们知道,SWbemServices和SWbemObject可以直接使用VBScript(或者WSH)的GetObject函数,加上WMI的连接符串Moniker(winmgmts:)和WMI的对象路径(如:"[\\ComputerName][\Namespace][:ClassName][.KeyProperty='Value']")来获得。而且SWbemLocator, SWbemLastError, SWbemObjectPath, SWbemNamedValueSet, SWbemSink, SWbemDateTime, and SWbemRefresher对象都可以使用这个函数来创建。其它的对象是通过调用方法或访问某项属性来获得,而不能通过GetObject或CreateObject来创建。
The object model also tells you that seven of the objects in the WMI scripting library expose a SWbemSecurity object, as indicated by the security callout icon immediately beneath or to the right of the object.
对象模型还告诉我们WMI脚本库中的七个对象还暴露出一个SWbemSecurity对象,。。。。。。。。。。。。。。。
For more information about a specific scripting library object, method, or property, see Scripting API for WMI in the WMI SDK Documentation. To understand the basic mechanics of the WMI scripting library, let's turn our attention to the seven WMI script templates we listed earlier. Before we do that, how about a paragraph or two about variable naming conventions.
对于特定的脚本库对库、方法或属性,请参考WMI SDK文档中的Scripting API for WMI,为理解WMI脚本库中的基本机制,我们先看一下前面列出的七个脚本模板。开始之前我们先了解一下参数的命名约定。
A Paragraph or Two About Variable Naming Conventions
参数的命名约定
In the example scripts that follow, the variable names used to reference each WMI automation object follow a consistent naming convention. Each variable is named according to the automation object's name in the WMI scripting library, and prefaced with "obj" (to indicate an object reference) or "col" (to indicate a collection object reference). For example, a variable that references a SWbemServices object is named objSWbemServices. A variable that references a SWbemObject is named objSWbemObject. And a variable that references a SWbemObjectSet is named colSWbemObjectSet.
在下面的例子中,WMI Automation Object的变量都遵守了前后一致的命名规则。每一个变量都按照WMI脚本库中的Automation Object的名称来进行命名,分别以obj(表示是一个对象变量)或col(表示是一个集合变量)开头。例如一个参考SWbemServices对象进行命名的变量可能是objSwbemServices,参考SWbemObject进行命名的可能是objSWbemObject,colSwbemObjectSet参考了SWbemObjectSet。
Why is this important? Well, one could certainly argue that it's not. However, the idea is to help you understand the type of WMI object you're working with at different points in a WMI script. If it helps, great. If it doesn't, just ignore it. The other mildly important thing to keep in mind is that the object reference variable names can be whatever suits your fancy. If you prefer variable names like foo and bar, or dog and cat, that's fine too. There is no requirement stating you must name a reference to a SWbemServices object objSWbemServices. That's just how we did it.
为什么这些很重要呢?是的,肯定会有人说这些并不重要。不过这可以帮你更好的理解WMI脚本中不同位置的各个对象的类型。如果它对你有帮助,那太好了;如果没有话,那就不会管它算了。另一个要注意的略微重要的事情是你也可以把变量按照你自己的意思进行命名,如果你喜欢使用foo或bar,cat 或 dog,那也很不错。这并不是必须要你这样开始命名变量。不过那正是我们的做法。
The Scripting Guys Guide to WMI Script Templates
编程人员的WMI脚本模板向导
Admittedly, WMI has a reputation for being very difficult to learn and even more difficult to use. In many respects, this reputation has been acquired not so much because WMI really is difficult, but simply because it is so big. WMI can be used to manage computer hardware, computer software, and nearly everything in between. The assumption is that any technology that encompasses so many different elements must be difficult.
不可否认地说,WMI有一个不好的名声:很难学习、而且使用起来更难。从很多方面来看,这个名声倒不是显得很过分因为WMI确实很难,但只是因为它特别的大。WMI可以用来管理计算机硬件、软件,包括几乎其中任何内容。想一下,任何一种技术都包含有许多不同的内容,综合起来肯定很不好学。
In reality, though, many of the tasks that can be performed by using WMI follow one of a handful of standard approaches. For example, you've already seen how a template can serve as the basis for scripts that return information about almost any managed resource. In Part 1 of this series, the same basic script (with one or two minor modifications) was used to return information about items as disparate as installed memory, services, and events recorded in the event logs.
实际上,其实许多任务可以使用大量的标准方法来执行。例如,你已经看到如何让一个模板来返回几乎所有的托管资源的信息。在这一系统的第一部分中,同样的简单脚本(会有一点点改动)可以用来获得各种不同项目的信息,如所安装的内存、服务日志记录中的事件。
The following topics present basic WMI script templates that can be used to:
- Retrieve instances of a managed resource.
- Display the properties of a managed resource.
- Modify the properties of a managed resource.
- Call a method of a managed resource.
- Create a new instance of a managed resource.
- Delete an instance of a managed resource.
- Subscribe to events to monitor the creation, modification, and/or deletion of a managed resource.
下列的题目提供的脚本模板可以用来:
1.可以获取WMI托管资源的实例
2.可以读取WMI托管资源的属性
3.可以修改WMI托管资源的属性
4.可以调用WMI托管资源的方法
5.可以在WMI托管资源中创建一个新的实例
6.可以在WMI托管资源中删除一个实例
7.可以订阅下列事件:对WMI托管资源的创建、修改、删除
Before we get started, we need to make sure we're perfectly clear on one important point: What you can and cannot do to a WMI managed resource is governed by the managed resource's blueprint (that is, class definition) in the Common Information Model (CIM) repository, and not the WMI scripting library. This is why Part 2 of this series is mildly important (hint, hint). Still not convinced? We'll give you a couple of examples.
在开始之前,我们要确定已经明白一个重点:对于WMI的某个托管资源,你能做的和不能做的是由CIM库中托管资源的蓝图(也就是类定义)决定的,而不是WMI的脚本库。这也是为什么这个系列的第二部分不是特别重要。还是不太确定?好的,我举个例子。
You can only modify writeable properties. How do you determine if a property is writeable? You use WbemTest.exe, WMI CIM Studio, WMIC.exe, or a script to examine the property's Write qualifier. (See Figure 7 or Listing C in Part 2 of this series for an example of how to examine property qualifiers.) If the Write qualifier isn't defined for a property, the default value is FALSE, which means the property is read-only.
你只能够修改可写的属性。但是你怎么样确定那个属性是可以写的呢?可以使用WbemTets.ext、Wmi CIM Studio、WMIC.exe或一个脚本来察看该属性的Write Qualifier(参考图七或第二部分的列表C来获知如何察看属性qualifiers)。如果Write Qualifer没有定义属性,那么默认的值是False,就是说是只读的。
Here's another example. You can only create new instances of managed resources if the resource's class definition sets the SupportsCreate class qualifier to TRUE. How do you determine if a managed resource's class definition sets SupportsCreate to TRUE? You examine the managed resource's class qualifiers, again, as shown in Figure 7 and demonstrated in Listing C in Part 2 of this series.
Note In practice you'll find some managed resources can be created, updated, and/or deleted even though the managed resource's class definition fails to set the appropriate qualifiers. We're told the situation is being corrected.
这里还有一个例子。如果托管资源的类定义将SupportsCreate类的Qualifier设置为了True,你也可以给托管资源创建新的实例。怎么查看SupportsCreate类的Qualifier是否设置为了True呢?如何判断一项托管资源的类定义是否设定SupportsCreate为True呢?可以察看一下托管资源的Qualifiers,如同图七(在Part 2中的List C部分)
One more thing before we get started. All of the following script templates are designed to work on the local computer. This is done by setting the value of the variable strComputer to a dot ("."). To run a script against a remote computer, simply set the value of strComputer to the name of the remote computer. For example, this line of code causes a script to run against a computer named atl-dc-01:
strComputer = "atl-dc-01"
在开始之前,还有一项内容要注意。下列所有的脚本模板都是在本地计算机上运行的,原因是strComputer变量的值是"."。如果在在远程的计算机上运行,只要把strComputer的值设置为远程计算机的名称。例如:下面一行代码就会使脚本在名为atl-dc-01的计算机上运行:
strComputer="atl-dc-01"
Retrieving Instances of a Managed Resource
Up to this point, we've used the SWbemServices InstancesOf method to retrieve instances of managed resources, as shown in Listing 1.
获取一项托管资源的实例
到目前为止,我们已经使用了SWbemServices InstancesOf方法来获取托管资源的实例,参看list 1
Listing 1. Retrieving services information using SWbemServices InstancesOf
List 1 使用SWbemServices Instancesof获取系统服务信息
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colSWbemObjectSet = objSWbemServices.InstancesOf("Win32_Service")
For Each objSWbemObject In colSWbemObjectSet
WScript.Echo "Display Name: " & objSWbemObject.DisplayName & vbCrLf & _
" State: " & objSWbemObject.State & vbCrLf & _
" Start Mode: " & objSWbemObject.StartMode & vbCrLf
Next
While InstancesOf certainly does the trick, what about situations where you only want a subset of instances or properties? Suppose you want to optimize instance and property retrieval to minimize network traffic. In such cases, you'll be glad to learn WMI supports a rich and powerful query facility.
当然InstancesOf可以完成这个小把戏,但是如果你只需要一部分的实例或属性值的话,比如打算优化实例和属性值的获取以最小化网络的流量。这种情况,你会很高兴能学习一些WMI所支持的大量功能强大的查询工具。
Querying WMI is the process of issuing a request for managed resources that match some predefined criteria. For example, a WMI query can request only those services with a StartMode of Auto that are in a Stopped state.
查询WMI是指对托管资源进行匹配条件查询的过程。例如,一个WMI查询可以只请求那些设置为自动但状态为停止的服务。
WMI queries provide a more efficient mechanism for retrieving instances of managed resources and their properties than the InstancesOf method. WMI queries return only those instances and properties that match the query, whereas InstancesOf always returns all instances of a specified resource and all of the properties for each instance. Also, queries are processed on the target computer identified in the object path rather than on the source computer running the script. Therefore, WMI queries can significantly reduce the amount of network traffic that would otherwise be encountered by less efficient data retrieval mechanisms, such as InstancesOf.
对于托管资源实例和属性值的获取,WMI查询提供了一个更有效的机制。WMI查询只返回和条件匹配的实例和属性值。而且查询过程是在目标机器的对象路径内运行的,而不是在运行脚本的机器上执行。因此WMI查询可以显著的减少网络流量,相对于其它效率不高的获取机制,例如InstancesOf。
To query WMI, you construct a query string using the WMI Query Language (WQL). The query string defines the criteria that must be satisfied to result in a successful match. After the query string is defined, the query is submitted to the WMI service using the SWbemServices ExecQuery method. Instances of managed resources that satisfy the query are returned to the script in the form of a SWbemObjectSet collection.
要使用WMI查询,你需要先使用WMI 查询语言(WQL)来创建一个查询字符串。查询字符串定义了匹配的条件,以得到相匹配的查询结果。定义好查询字符串后,使用SWbemServices ExecQuery方法来将查询字符串提交到WMI服务。符合查询条件的实例会以SWbemObjectSet集合的形式返回到脚本。
Using WQL and the ExecQuery method (rather than InstancesOf) provides you with the flexibility to create scripts that return only the items that are of interest to you. For example, you can use a basic WQL query to return all properties of all instances of a given managed resource, as shown in Listing 2. This is the same information that is returned by the InstancesOf method. If you compare Listings 1 and 2, you'll notice the bold part of Line 3 is the only difference between the two scripts.
使用WQL和ExecQuery方法(而不是InstancesOf)可以灵活的创建佳脚本,从而可以只返回你感兴趣的内容。例如,可以使用基本的WQL查询来返回给定托管资源所有实例的所有属性,如List2所示。这和InstancesOf方法返回的信息是相同的。如果比较一下List1和List2,就会两个发现脚本只有第三行的粗体部分不同。
Listing 2. Retrieving services information using SWbemServices ExecQuery
List2.使用SWbemServices ExecQuery来获取系统服务信息。
strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colSWbemObjectSet = objSWbemServices.ExecQuery("SELECT * FROM Win32_Service")
For Each objSWbemObject In colSWbemObjectSet
WScript.Echo "Display Name: " & objSWbemObject.DisplayName & vbCrLf & _
" State: " & objSWbemObject.State & vbCrLf & _
" Start Mode: " & objSWbemObject.StartMode & vbCrLf
Next
You can also create targeted queries using WQL, queries that do such things as:
- Return only selected properties of all the instances of a managed resource.
"SELECT DisplayName, State, StartMode FROM Win32_Service" - Return all the properties of selected instances of a class.
"SELECT * FROM Win32_Service WHERE State = 'Stopped'" - Return selected properties of selected instances of a class.
"SELECT DisplayName,State,StartMode FROM Win32_Service WHERE State='Stopped'"
用户也可以创建带有目标的WQL,比如可以完成下列任务的查询:
- 返回某个托管资源所有实例的所选属性
"SELECT DisplayName, State, StartMode FROM Win32_Service"
- 返回某个类的所选实例的属性
"SELECT * FROM Win32_Service WHERE State = 'Stopped'"
- 返回某个类的所选实例的特定属性
"SELECT DisplayName,State,StartMode FROM Win32_Service WHERE State='Stopped'"
Creating targeted queries will sometimes noticeably increase the speed with which data is returned. (For instance, it's much faster to return only those events in the Application event log that have EventCode 0 than to return all the events in all the event logs.) Targeted queries also make it easier to work with the returned data. For example, suppose you want only events from the Application event log with EventCode 0. Using a targeted query will return only those items. By contrast, InstancesOf would return all the events, and you would have to individually examine each one and determine whether it, 1) came from the Application event log and, 2) has EventCode 0. Although this can be done, it is less efficient and requires additional work on your part.
创建带有目标的查询有时可以明显地加快返回数据的速度。(例如,只返回应用程序事件日志中EventCode为0的纪录比返回事件日志的所有事件快很多。)带有目标的查询也是返回数据的下一步处理工作变得简单。例如,假设只需要应用程序日志中的EventCode为0的事件。使用带有目标的查询就会只返回这些内容,相对来说,如果使用InstancesOf的话就会返回所有的事件,你不得不一一察看他们是否:1)来自于应用程序事件,2)EventCode是否为0。当然这也可以完成,但是效率偏低,而且需要额外的工作。
Targeted queries can also cut down on the amount of data that is returned, an important consideration for scripts that run over the network. Table 1 shows some relative figures for different query types. As you can see, there can be a considerable difference in the amount of data returned by the various query types.
对于在网络上运行的脚本尤其要考虑的是,带有目标的查询还可以减少返回的数据的量。对于不同的查询类型,表一列出了一些相对的数字,可以看出不同查询类型返回的数据会大不相同。
Table 1. Comparing different WMI instance retrieval methods and queries
表一
比较不同的WMI实例获取方法和查询
Method/WQL Query Bytes Returned
调用方法/WQL查询返回的字节
objSWbemServices.InstancesOf("Win32_Service") 157,398
objSWbemServices.ExecQuery("SELECT * FROM Win32_Service") 156,222
objSWbemServices.ExecQuery("SELECT Name FROM Win32_Service") 86,294
objSWbemServices.ExecQuery("SELECT StartMode FROM Win32_Service") 88,116
objSWbemServices.ExecQuery("SELECT StartMode FROM Win32_Service WHERE State='Running'") 52,546
objSWbemServices.ExecQuery("SELECT StartMode, State FROM Win32_Service WHERE State='Running'") 56,314
objSWbemServices.ExecQuery("SELECT * FROM Win32_Service WHERE Name='WinMgmt'") 27,852
objSWbemServices.Get("Win32_Service.Name='WinMgmt'") 14,860
At this point, we hope we've convinced you ExecQuery is superior to InstancesOf. Now let's turn Listing 2 into a generic WMI script template that can easily be modified to retrieve instances of any WMI managed resource. Listing 3 contains our first template.
现在希望你已经确信ExecQuery比InstancesOf更方便。现在我们把List2改写成一个通用的WMI脚本模板,这样我们就可以通过简单修改来获取任何WMI托管资源的实例。List3 就是新的模板。
Listing 3. Template for retrieving instances of managed resources
List3 获取托管资源的模版
strComputer = "."
strNamespace = "\root\cimv2"
strClass = "Win32_Service"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set colSWbemObjectSet = objSWbemServices.ExecQuery("SELECT * FROM " & strClass)
For Each objSWbemObject In colSWbemObjectSet
WScript.Echo "Display Name: " & objSWbemObject.DisplayName
WScript.Echo "State: " & objSWbemObject.State
WScript.Echo "Start Mode: " & objSWbemObject.StartMode
Next
To use this template with other WMI classes:
- Set the value of strClass to the appropriate WMI class for the target-managed resource.
- If necessary, set the value of strNamespace to the WMI namespace for the target class.
- Replace the statements within the For Each loop that echo the properties and their values. Remove the following lines and replace them with the appropriate lines of code for the property values being displayed.
WScript.Echo "Display Name: " & objSWbemObject.DisplayName
WScript.Echo "State: " & objSWbemObject.State
WScript.Echo "Start Mode: " & objSWbemObject.StartMode
如何使用此模版办获取其它WMI类的信息:
- 设置strClass的值为要查询的托管资源对应的WMI类
- 如果有必要,还需要将strNampspace的值修改为要查询的类的WMI命名空间
- 替换掉For Each循环中的输出属性及值的语句。将下面的几行用相应的要显示的代码替换掉。
WScript.Echo "Display Name: " & objSWbemObject.DisplayName
WScript.Echo "State: " & objSWbemObject.State
WScript.Echo "Start Mode: " & objSWbemObject.StartMode
Scripting Guys Freebie If you're working with a managed resource that returns a lot of instances (we'll define a lot as more than 1000 for the purpose of this discussion), you can optimize the behavior of ExecQuery through the use of optional flags. For example, suppose you use ExecQuery to query Event Log records (modeled by the Win32_NTLogEvent class). As you already know, the Event Log(s) can contain thousands and thousands of records. By default, you may encounter performance problems associated with queries that return large result sets, such as Event Log queries. The reason has to do with the way WMI caches a SWbemObject reference for each and every instance, or in our example, for each and every Event Log record. To avoid the problem, you can tell ExecQuery to return a forward-only SWbemObjectSet, as demonstrated below.
编程人员提示:如果工作中涉及到会返回大量实例的托管资源(我们在讨论中设定多于1000的为大量),可以使用ExecQuery的选项来进行优化。例如,假设使用ExecQuery来查询事件日志(使用Win32_NtLogEvent类)。我们都已经知道,日志中可能包含有几千条记录。默认情况下,你可能会遇到性能问题,因为查询会返回大量的结果。所以一定要这样做的原因就是WMI可以缓存每个实例的SWbemObject的引用(在我们的例子中就是指每一条事件记录)。为避免这个问题,你可以指定让ExecQuery只返回一个Forward-Only的SWbemObjectSet,如下例。
strComputer = "."
strNamespace = "\root\cimv2"
strClass = "Win32_NTLogEvent"
Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set colSWbemObjectSet = objSWbemServices.ExecQuery("SELECT * FROM " & strClass, _
"WQL" _
wbemFlagReturnImmediately + wbemFlagForwardOnly)
' Insert remainder of script here (e.g., For Each Next loop)...
Note The wbemFlagReturnImmediately flag (which is defined in one of the enumerations we briefly touched on earlier) is the default ExecQuery behavior and is semi-synchronous. The important optimization is the addition of the wbemFlagForwardOnly flag. Combining wbemFlagReturnImmediately with wbemFlagForwardOnly results in a forward-only enumerator. A forward-only enumerator performs much faster than the default enumerator, because WMI doesn't maintain references to objects in the SWbemObjectSet.
注意:wbemFlagReturnImmediately(这是在我们以前简单介绍过的一个枚举中定义的)标志是默认的ExecQuery查询动作,是半同步的。起主要优化作用的是后面的wbemFlagForwardOnly标志。WebemFalgReturnImmediately和WbemFlagForwardOnly的组合使用会返回一个Forward-Only的枚举器。Forward-Only的枚举器比默认的要快很多,因为WMI不用一直保持对SWbemObjectSet中对象的引用。
Displaying the Properties of a Managed Resource
One limitation of the script shown in Listing 3 is that it requires you to know, in advance, the names of all of the properties that you want to retrieve and display. What if you want to display values for all the properties of a resource, but you either do not know the property names or do not want to type the 40 or 50 lines of code required to display each property value? In that case, you can use the template in Listing 4, which automatically retrieves and displays the values of each property found in a class.
显示托管资源的属性值
List3中的脚本有一个局限的地方就是,你需要预先知道要获取并显示的属性的所有名称。如果你要显示托管资源的所有属性,但是却不知道属性的名称,或不愿去敲那4、50行能显示每个属性值的代码的话,就可以使用List4的模板,List4能够自动获取并显示一个类中每一项属性的值。
Listing 4. Scriptomatic lite template
strComputer = "."
strNamespace = "\root\cimv2"
strClass = "Win32_Process"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set colSWbemObjectSet = objSWbemServices.ExecQuery("SELECT * FROM " & strClass)
Wscript.Echo "Scriptomatic Lite - Class: " & strClass
Wscript.Echo "===========================" & String(Len(strClass), "=") & vbCrLf
intInstance = 1
For Each objSWbemObject In colSWbemObjectSet
WScript.Echo "Instance: " & intInstance & vbCrLf & "--------------"
For Each objSWbemProperty In objSWbemObject.Properties_
strPropertyValue = ConvertPropertyValueToString(objSWbemProperty.Value)
WScript.Echo objSWbemProperty.Name & ": " & strPropertyValue
Next
WScript.Echo
intInstance = intInstance + 1
Next
Function ConvertPropertyValueToString(ByVal PropertyValue)
If IsObject(PropertyValue) Then
ConvertPropertyValueToString = "<CIM_OBJECT (embedded SWbemObject)>"
ElseIf IsNull(PropertyValue) Then
ConvertPropertyValueToString = "<NULL>"
ElseIf IsArray(PropertyValue) Then
ConvertPropertyValueToString = Join(PropertyValue, ",")
Else
ConvertPropertyValueToString = CStr(PropertyValue)
End If
End Function
To use this template with other WMI classes:
- Set the value of strClass to the appropriate WMI class for the target-managed resource.
- If necessary, set the value of strNamespace to the WMI namespace for the target class.
如何在此脚本上使用其它的WMI类:
- 设置strClass为目标资源的相应WMI类
- 如果需要,设置strNamespace为目标类的WMI命名空间
Modifying the Properties of a Managed Resource
In Windows 2000, WMI is primarily a read-only technology. Of the 4,395 properties defined in the Windows 2000 root\cimv2 namespace, only 39 properties are writeable. Those numbers improve in Microsoft® Windows® XP, where 145 of approximately 6560 properties are writeable. And the numbers get even better in Windows Server 2003.
修改托管资源的属性
在Windows2000中,WMI大多情况下是只读。在Windows2000 root\cimv2命名空间下定义的4395个属性中,只有39个是可写的。这个数字在XP中有所增加,在大约6560个属性中有145个是可写的,而且在2003系统中更多。
The template in Listing 5 demonstrates how to modify a writeable property. The script retrieves all instances of the managed resource modeled by the Win32_OSRecoveryConfiguration class. (In this case, the class contains only a single instance.) The script provides new values for three properties—DebugInfoType, DebugFilePath, and OverWriteExistingDebugFile—and then commits the changes (and thus configures operating system recovery options) using the SWbemObject Put_ method. If you forget to call the Put_ method, the changes will not be applied.
Note This template works only for properties that are writeable. Attempting to change a read-only property will result in an error. To determine if a property is writeable, examine the property's Write qualifier.
List5的模板演示了如何修改一个可写的属性。这个脚本获取了Win32_OSRecoveryConfiguration类中的所有实例(其实在这个类中只有一个实例)。脚本给三个属性-DebugInfoType,DebugFilePath和OverWriteExistingDebugFile-设置了新的值,并使用SWbemObject Put_方法提交了修改(实际上是配置了操作系统的恢复选项)。如果你最后忘记了调用Put_方法,所作的改变是不会被应用的。
Listing 5. Template for modifying writeable properties of a managed resource
List5 修改托管资源中可写属性的模板
strComputer = "."
strNamespace = "\root\cimv2"
strClass = "Win32_OSRecoveryConfiguration"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set colSWbemObjectSet = objSWbemServices.ExecQuery("SELECT * FROM " & strClass)
For Each objSWbemObject In colSWbemObjectSet
objSWbemObject.DebugInfoType = 1
objSWbemObject.DebugFilePath = "c:\tmp\memory.dmp"
objSWbemObject.OverWriteExistingDebugFile = False
objSWbemObject.Put_
Next
Notice how SWbemObject is used inside the For Each loop to: 1) Directly access and modify properties defined by the Win32_OSRecoveryConfiguration class, and 2) call its own Put_ method to commit the change.
注意SWbemObject是如何在循环中使用的 1)直接访问并修改 Win32_OSRecoveryConfiguration定义的属性 2)使用自带的方法 Put_提交。
To use this template with other WMI classes that implement writeable properties:
- Set the value of strClass to the appropriate WMI class for the target-managed resource.
- If necessary, set the value of strNamespace to the WMI namespace for the target class.
- Replace the statements within the For Each loop that configure new property values. Remove the following lines, and replace them with the appropriate lines of code for the properties being modified:
objSWbemObject.DebugInfoType = 1
objSWbemObject.DebugFilePath = "c:\tmp\memory.dmp"
objSWbemObject.OverWriteExistingDebugFile = False
- 如何在其它的WMI类上应用此模板
- 设置strClass为目标托管资源的相应WMI类
- 如果需要,设置相strNamespace为相应的WMI命名空间
- 替换掉循环中的相应属性。去掉下列行,并使用带有要修改的属性的相应代码
objSWbemObject.DebugInfoType = 1
objSWbemObject.DebugFilePath = "c:\tmp\memory.dmp"
objSWbemObject.OverWriteExistingDebugFile = False
Calling a Method of a Managed Resource
Methods defined in a managed resource's class definition allow you to perform actions on the managed resource. For example, the Win32_Service class includes methods that let you perform such tasks as starting and stopping services; the Win32_NTEventlogFile class includes methods for backing up and clearing event logs; the Win32_OperatingSystem class includes methods for rebooting or shutting down a computer.
如何调用托管资源的方法
通过调用托管资源类中定义的方法可以在托管资源上执行一些动作。例如Win32_Service类就有起停服务的方法可以调用;Win32_NTEventlogFile类有备份和清除日志的方法;Win32_OperatingSystem类中包含有重起和关机的方法。
Listing 6 provides a template that can be used to write scripts that call WMI managed resource methods. This particular script uses the StopService method of the Win32_Service class to stop the Alerter service on the local computer.
Note Before you can call a method defined in a managed resource's class definition, the method must be implemented. How do you determine if a method is implemented? Examine the method's implemented qualifier. A value of TRUE indicates that a method has an implementation supplied by a provider. Having said that, be aware that some methods do not define the implemented qualifier although the method is implemented. The Win32_Service StopService method, shown below, is an example of such a method. The bottom line is determining whether or not a method is implemented can also involve a bit of trial and error. As we mentioned earlier, we're told the situation is being corrected.
List6提供了一个调用WMI托管资源方法的脚本模板。它使用了Win32_service类中的StopServie方法来停止本地计算机的Alerter服务。
注意:在调用某托管资源的方法之前,应该先确认此方法可以执行。如何确定此方法可以执行呢,可以查看这个方法的implemented的修饰词(qulifier),如果Provider提供的值为True,表示可以执行。虽然这样说,但是要注意有此方法虽然可以调用,但是并没有定义Implemented。下面例子中调用的Win32_Service的StopService就是其中的一种。所以可以进行一些试验来了解是否有可调用的方法,虽然也可能遇到一些错误。据说这种情况正在进行修正。
Listing 6. Template for calling a method of a managed resource
strComputer = "."
strNamespace = "\root\cimv2"
strClass = "Win32_Service"
strKey = "Name"
strKeyValue = "Alerter"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set colSWbemObjectSet = objSWbemServices.ExecQuery _
("SELECT * FROM " & strClass & " WHERE " & strKey & "='" & strKeyValue & "'")
For Each objSWbemObject in colSWbemObjectSet
objSWbemObject.StopService()
Next
To use this template with other WMI classes:
- Set the value of strClass to the appropriate WMI class for the target-managed resource.
- If necessary, set the value of strNamespace to the WMI namespace for the target class.
- Set the value of strKey to the name of the property that forms the basis of the WHERE clause.
- Set the value of strKeyValue to an appropriate value for strKey.
- Replace the statement within the For Each loop that calls the method. Remove the following line, and replace it with the appropriate line of code for the method being called. If necessary, you must also include the appropriate method parameters.
objSWbemObject.StopService()
如何将此脚本应用到其它WMI类
- 如何在其它的WMI类上应用此模板
- 设置strClass为目标托管资源的相应WMI类
- 根据Where子句的规则设置符合相应属性的strKey的值
- 设置strKeyValue的值能够适合strKey
- 替换掉循环中调用的方法。去掉下面几行,并用相应的方法调用代码来替换,如果需要还可以设定方法的参数。
- objSWbemObject.StopService()
Creating a New Instance of a Managed Resource
Some WMI classes allow you to create a new instance of the resource they model. For example, you can use the Win32_Environment class to create environment variables, the Win32_Process class to create processes, and the Win32_Share class to create shared resources, to name a few.
创建一个新的托管代码的实例
一些WMI类允许用户创建自定义模块的实例。例如,可以使用Win32_Environment类来创建环境变量,用Win32_Process类来创建进程,用Win32_share类来创建共享资源。而且不只这些,可以再列一些类似的类出来。
Before you create a new instance of a resource, you must verify that the managed resource's class supports the create operation. You do this by examining the class's SupportsCreate qualifier. A value of TRUE indicates the class supports the creation of instances (the default is FALSE). Once you've determined the class supports the create operation, you must determine the method used to create new instances. There are two approaches to creating new instances:
- If the class defines the CreateBy class qualifier with a value of PutInstance, you use the SWbemObject SpawnInstance_ and Put_ methods to create the new instance.
- If the value assigned to the CreateBy class qualifier is something other than PutInstance (Create, for example), you use the method identified by the CreateBy qualifier to create the new instance.
在创建新的实例之前,必须先确定此托管资源的类是否支持创建操作。用户可以通过察看类的SupportCreate的Qualifier来确定,True表示这个类支持创建实例的操作(默认的是False)。确定类支持创建新的实例后,还要了解要使用那些方法。一般有两种方式:
- 如果类定义中CreateBy 的Qualifier值为PutInstance,可以使用SWbemObject SpawnInstance_和Put_方法来创建新的实例
- 如果类定义中CreateBy 的Qualifier值不是PutInstance(比如 Create),就必须使用CreateBy的Qualifier指明的方法来创建新的实例
Let's look at a template for each.
Listing 7 demonstrates how to create an instance of a resource when the resource's class definition sets SupportsCreate to TRUE and CreateBy to PutInstance. After connecting to WMI on the target computer, your first step is obtaining the blueprint (that is, class definition) for the thing you're creating. To do that, you use the SWbemServices Get method to fetch the actual WMI class (rather than retrieve instances of the class). After you have an object representing the class, use the SWbemObject SpawnInstance_ method to create a new, "blank," instance of the class. Set the properties for the new instance, and call the SWbemObject Put_ method to create the new instance.
我们分别来看两个例子
List7演示了在第一种情况时,如何创建一个实例。当连接到目标机器上的WMI后,第一步要获取所要创建内容的类定义(蓝图),这一步使用SWbemServices Get方法来获取WMI类(而不是获取类的实例)。获取到一个表示此类的对象后,使用SWbemObject SpawInstalce_方法来创建一个新的、“空白”的实例。然后给新的实例设置属性,最后使用SWbemObject Put_方法将属性提交给新的实例。
Listing 7. Template for creating a new instance using SpawnInstance_ and Put_
List7 使用SpawnInstance_ 和Put_来创建新的实例的模板
strComputer = "."
strNamespace = "\root\cimv2"
strClass = "Win32_Environment"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set objSWbemObject = objSWbemServices.Get(strClass)
Set objNewSWbemObject = objSWbemObject.SpawnInstance_()
objNewSWbemObject.Properties_.Item("Name") = "TMPSHARE"
objNewSWbemObject.Properties_.Item("UserName") = "<SYSTEM>"
objNewSWbemObject.Properties_.Item("VariableValue") = "c:\tmp"
objNewSWbemObject.Put_
To use this template with other WMI classes that support PutInstance:
- Set the value of strClass to the appropriate WMI class for the target-managed resource.
- If necessary, set the value of strNamespace to the WMI namespace for the target class.
- Replace the statements that configure the values for the environment variable. Remove the following lines, and replace them with the appropriate lines of code for the object being created:
objNewSWbemObject.Properties_.Item("Name") = "TMPSHARE"
objNewSWbemObject.Properties_.Item("UserName") = "<SYSTEM>"
objNewSWbemObject.Properties_.Item("VariableValue") = "c:\tmp"
Scripting Guys Freebie When creating a new instance using the SWbemObject SpawnInstance_ and Put_ methods, you must provide value(s) for all of the class's key properties. For example, the Win32_Environment class used in Listing 7 defines two key properties: Name and UserName. How do you determine a class's key(s) property or properties? You use WbemTest.exe, WMI CIM Studio, WMIC.exe, or a script to examine the property's Key qualifier.
如何将此脚本应用到其它支持PutInstance的WMI类
- 如何在其它的WMI类上应用此模板
- 设置strClass为目标托管资源的相应WMI类
- 替换掉配置环境变量的语句。去掉下列几行语句,并使用相应的代码替换
objNewSWbemObject.Properties_.Item("Name") = "TMPSHARE"
objNewSWbemObject.Properties_.Item("UserName") = "<SYSTEM>"
objNewSWbemObject.Properties_.Item("VariableValue") = "c:\tmp"
编程人员的提示:当使用SWbemObject SpawnInstance_和Put_方法创建新的实例时,必须给所有的类关键属性赋值。例如List7中使用的Win32_Enviroment类有两个关键属性Name和Username。怎样知道一个类的关键属性呢,可以使用WbemTest.exe、WMI CIM Studio、WMIC.exe或一个可以检查属性的Key qualifier字段的脚本。
Listing 8 demonstrates how to create an instance of a resource when the resource's class definition provides its own create method. After connecting to WMI on the target computer, your first step is obtaining the blueprint (that is, class definition) for the thing you're creating. To do that, you use the SWbemServices Get method to fetch the actual WMI class (rather than retrieve instances of the class). After you have an object representing the class, use SWbemObject to call the method identified by the class's CreateBy qualifier. The script template in Listing 8 uses the Win32_Share Create method to create a new shared folder.
List8演示了当资源的类定义提供了自己的创建方法时,新建实例的过程。连接到目标计算机的WMI之后,第一步还是获取相应的类定义。这一步同样使用SWbemServices Get方法来获取WMI类(而不是获取类的实例)。然后使用SWbemObject来调用类的CreateBy Qualifier指明的方法,List8使用了Win32_ShareCreate方法来创建了一个新的共享文件夹。
Listing 8. Template for creating a new instance using a managed resource method
strComputer = "."
strNamespace = "\root\cimv2"
strClass = "Win32_Share"
Const SHARED_FOLDER = 0
strPath = "c:\tmp"
strShareName = "tmp"
intMaximumAllowed = 1
strDescription = "Temporary share"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set objSWbemObject = objSWbemServices.Get(strClass)
intReturnValue = objSWbemObject.Create(strPath, _
strShareName, _
SHARED_FOLDER, _
intMaximumAllowed, _
strDescription)
WScript.Echo "Return value: " & intReturnValue
To use this template with other WMI classes that provide a custom create method:
- Set the value of strClass to the appropriate WMI class for the target-managed resource.
- If necessary, set the value of strNamespace to the WMI namespace for the target class.
- Replace the statements that initialize the variables that represent the parameters passed to the create method. Remove the following lines, and replace them with the appropriate lines of code for the object being created:
Const SHARED_FOLDER = 0
strPath = "c:\tmp"
strShareName = "tmp"
intMaximumAllowed = 1
strDescription = "Temporary share" - Replace the Win32_Share Create method call with the appropriate method for the managed resource you're creating. Remove the following lines, and replace them with the appropriate lines of code for the object being created:
intReturnValue = objSWbemObject.Create(strPath, _
strShareName, _
SHARED_FOLDER, _
intMaximumAllowed, _
strDescription)
Scripting Guys Freebie When creating a new instance using a method provided by a managed resource's class definition, you must provide values for any mandatory parameters defined by the method. For example, the Win32_Share class used in Listing 8 defines three mandatory parameters: Path, Name, and Type. How do you determine a method's mandatory parameters? Refer to the managed resource's class definition in the WMI SDK.
如何将此脚本应用到其它提供了自定义创建实例方法的WMI类
- 如何在其它的WMI类上应用此模板
- 设置strClass为目标托管资源的相应WMI类
- 删除下列行,并使用相应的代码:
Const SHARED_FOLDER = 0
strPath = "c:\tmp"
strShareName = "tmp"
intMaximumAllowed = 1
strDescription = "Temporary share"
- 替换掉Win32_Share Create方法,并调用托管资源相应的方法。删除下列几行,并使用相应的代码。
intReturnValue = objSWbemObject.Create(strPath, _
strShareName, _
SHARED_FOLDER, _
intMaximumAllowed, _
strDescription)
编程人员提示: 当使用托管资源的类定义中提供的方法创建实例时,必须给方法中定义的所有强制(Mandatory)参数赋值。例如Win32_Share类定义了三个强制参数:Path、Name和Type。怎样才能知道那些是强制参数呢,可以参考WMI SDK中的托管资源的类定义。
Deleting an Instance of a Managed Resource
If you can create new instances of managed resources, it stands to reason you can delete instances too, and you can. In fact, the rules that govern which managed resource instances you can delete are strikingly similar to those governing the create operation. Let's review the requirements, and then we'll look at a couple of examples.
删除托管资源中的一个实例
如果你给托管资源创建实例,那就意味着也可以删除一个实例,而且这也是可以的。实际上删除实例的规则和创建实例的规则是类似的。我们来看一下删除实例的要求和几个例子。
Before you delete an instance of a resource, you must verify that the managed resource's class supports the delete operation. You do this by examining the class's SupportsDelete qualifier. A value of TRUE indicates the class supports delete (the default is FALSE). Once you've determined the class supports delete, you must determine the method used to delete instances. There are a couple of approaches to deleting instances:
- If the class defines the DeleteBy class qualifier with a value of DeleteInstance, you can use SWbemServices Delete or the SWbemObject Delete_ method to delete an instance.
- If the value assigned to the DeleteBy class qualifier is something other than DeleteInstance (delete, for example), you use the method identified by the DeleteBy qualifier to delete an instance.
在删除一个实例之前,必须确定托管资源的类定义支持删除操作。可以察看一下类的SupportDelete qualifier来确认,如果值为True表示可以删除(默认为False)。确定可以删除实例的操作之后,还要了解操作所使用的方法。下面有两种删除实例的方式:
- 如果类定义中的DeleteBy Qualifier值为DeleteInstance,可以使用SWbemServices Delete或 SWbemObject Delete_方法来删除实例。
- 如果类定义中的DeleteBy Qualifier值不是DeleteInstance(例如Delete),那么必须使用DeleteBy Qualifier指明的方法来删除。
Listings 9 and 10 demonstrate how to delete the environment variable created in Listing 7. Listing 9 uses the SWbemServices Delete method and Listing 10 uses the SWbemObject Delete_ method. You can use Listings 9 or 10 when the resource's class definition sets SupportsDelete to TRUE and DeleteBy to DeleteInstance.
List9和List10演示了如何删除在List7和List8中创建的环境变量。List9使用了SWbemServices Delete方法,List10使用了SWbemOBject Delete_方法。如果托管资源的类定义中SupportDelete为True且DeleteBy为DeleteInstance的话,可以使用List9和List10来作模板。
Listing 9. Template for deleting an instance using the SWbemServices Delete method
strComputer = "."
strNamespace = "\root\cimv2"
strInstance = "Win32_Environment.Name='TMPSHARE',UserName='<SYSTEM>'"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
objSWbemServices.Delete strInstance
Listing 10. Template for deleting an instance using the SWbemObject Delete_ method
strComputer = "."
strNamespace = "\root\cimv2"
strInstance = "Win32_Environment.Name='TMPSHARE',UserName='<SYSTEM>'"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set objSWbemObject = objSWbemServices.Get(strInstance)
objSWbemObject.Delete_
To use these templates with other WMI classes that support DeleteInstance:
- Set the value of strInstance to the appropriate WMI class, key(s), and key value(s) for the target-managed resource instance.
如何将此脚本应用到其它支持DeleteInstance的WMI类
- 设置strInstance的值为相应的WMI类、Key及Key的值
Listing 11 deletes the shared folder created in Listing 8, and in so doing, demonstrates how to delete an instance of a resource when the resource's class definition provides its own delete method. Take a second to compare Listings 10 and 11. See any difference outside of the obvious value assigned to strInstance? Listing 10 uses the SWbemObject Delete_ method (note the underscore) to delete instances when the managed resource's class definition sets the DeleteBy class qualifier to DeleteInstance. Listing 11, on the other hand, is using the Win32_Share Delete method.
List11,删除了List8创建的共享文件夹,整个过程演示了类定义提供了自己的删除方法时如何进行删除实例的操作。花一点时间比较一下List10和List11,除了对strInstance的赋值的不同,看到了其它的了吗?List10使用了SWbemObject Delete_方法(注意下划线),List11使用了Win32_share Delete方法。
Listing 11. Template for deleting an instance using a managed resource method
strComputer = "."
strNamespace = "\root\cimv2"
strInstance = "Win32_Share.Name='tmp'"
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & strNamespace)
Set objSWbemObject = objSWbemServices.Get(strInstance)
objSWbemObject.Delete
To use this template with other WMI classes that provide a custom delete method:
- Set the value of strInstance to the appropriate WMI class, key(s), and key value(s) for the target-managed resource instance.
如何将此脚本应用到其它支持DeleteInstance的WMI类
- 设置strInstance的值为相应的WMI类、Key及Key的值
Subscribing to Events
Okay. It's time to practice programmer virtue number one: laziness! Don't worry, we're still going to cover event subscriptions. However, rather than cover them here, we're going to point you to our sister publication: TechNet's Tales from the Script column, where we just published A Brief Introduction to WMI Events. So in addition to getting an introduction to WMI event subscriptions, you discover yet another scripting resource.
All for Now
This ends our trilogy on WMI scripting. Admittedly, there's more to cover and we will. If you'd like to send us suggestions for Scripting Clinic topics you'd like to read, we'd love to hear them. You can drop us a note at scripter@microsoft.com or in the User Comments at the top of this page.
One more thing before we forget. Remember the Microsoft Windows 2000 Scripting Guide, Automating System Administration book we mentioned at the beginning of the article? Well, it's done! And while we hope you all rush out and buy a copy—Bookpool is cheapest technical book e-tailer on the planet by the way—we also recognize the planet is full of cheapskates, such as ourselves. For that reason, we've also posted all 1328 pages of the book online. So the next time Scripting Clinic is, um, late, you have somewhere to turn. Should you decide to read all or some of the book, by all means, let us know what you think—good, bad, or ugly. Of course, we're more interested in what's missing and what we can do to improve version 2. Have fun!
Scripting Clinic
Greg Stemp has long been acknowledged as one of the country's foremost authorities on scripting, and has been widely acclaimed as a world-class... huh? Well, how come they let football coaches make up stuff on their resumes? Really? He got fired? Oh, all right. Greg Stemp works at... Oh, come on now, can't I even say that? Fine. Greg Stemp gets paid by Microsoft, where he tenuously holds the title of lead writer for the System Administration Scripting Guide.
Dean Tsaltas is a Nova Scotian living in Redmond. He has become fluent in American and even chuckles at the accent of his friends and family back in the Maritimes. He got his start in computing at a tender age when his grandma and parents chipped in and bought him his beloved C-64 and a subscription to Compute!'s Gazette. He has been at Microsoft for a couple of years now and has a message for friends and family back home and in Vancouver: "No, I have not met Bill!"
Bob Wells wanders around aimlessly espousing the virtues of scripting to anyone who will listen. Rumor has it that Bob's two dachshunds know more about scripting than most humans. In his spare time, Bob contributes to the System Administration Scripting Guide.
Ethan Wilansky spends a lot of his work time writing and consulting. He's crazy about scripting, Yoga, gardening, and his family (not necessarily in that order). He is currently working on a way to create script that will take out the trash and wash the dinner dishes.