<p><strong>五、获得类的集合对象的方法</strong></p><p>方法1.使用InstancesOf方法</p><blockquote dir="ltr" style="margin-right: 0px"><p>InstancesOf方法的语法参数格式如下:</p><p>SwbemServices.InstancesOf(strClass)</p><p>strClass为类名,例如"Win32_Service"。</p><p>范例:<span class="re0">$wbemObjectSet</span> = <span class="re0">$wbemServices</span>.<span class="me1">InstancesOf</span><span class="br0">(</span><span class="st0">"Win32_Service"</span><span class="br0">)</span></p><p>我在第一个例子里就是用这种方法来获取Win32_LogicalMemoryConfiguration类的实例集合。</p></blockquote><p>方法2.使用ExecQuery方法</p><blockquote dir="ltr" style="margin-right: 0px"><p>与InstancesOf方法不同,ExecQuery方法可以通过查询语句,只返回匹配部分实例和属性。ExecQuery方法的语法参数格式如下:</p><p>SwbemServices.ExecQuery(strQuery, [ strQueryLanguage = "WQL" ],[ iFlags ],[ objWbemNamedValueSet ]</p><p>strQuery为WQL(WMI Query Language)查询的字符串,具体语法可以查看<a href="http://msdn2.microsoft.com/en-us/library/aa392902.aspx">这里</a>,下面是几个例子:</p><p>SELECT * FROM Win32_LogicalDisk ; 即获取Win32_LogicalDisk类的全部集合对象</p><p>SELECT * FROM Win32_NTLogEvent WHERE Logfile = 'Application",,48 ; 从Win32_NTLogEvent类中获取名为"Application"的全部实例</p><p>SELECT * FROM __InstanceModificationEvent WITHIN 10 WHERE TargetInstance ISA 'Win32_Service' AND TargetInstance._Class = 'win32_TerminalService' ; 当Win32_NTLogEvent有新的实例建立时发出通知(这属于WMI事件,具体内容后文再提)</p><p>而ExecQuery方法的后几个参数很少会用到,有兴趣的话可以在<a href="http://msdn2.microsoft.com/en-us/library/aa393866.aspx">这里</a>了解更多。</p><p>使用范例:<span class="re0">$wbemObjectSet</span> = <span class="re0">$wbemServices</span>.<span class="me1">ExecQuery</span><span class="br0">(</span><span class="st0">"select * from Win32_Service"</span><span class="br0">)</span></p></blockquote><p dir="ltr">方法3.使用Get方法</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr">和上面两种方法不同,Get方法获得的是单个的对象。</p><p dir="ltr">比方说,下面的代码能列举出全部的系统服务:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><br /><span class="re0">$wbemServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2"</span><span class="br0">)</span><br /><br /><span class="re0">$wbemObjectSet</span> = <span class="re0">$wbemServices</span>.<span class="me1">InstancesOf</span><span class="br0">(</span><span class="st0">"Win32_Service"</span><span class="br0">)</span><br /><br /><br /><span class="kw1">For</span> <span class="re0">$wbemObject</span> <span class="kw1">In</span> <span class="re0">$wbemObjectSet</span><br /><span class="kw3">ConsoleWrite</span><span class="br0">(</span><span class="st0">"Name: "</span> & <span class="re0">$wbemObject</span>.<span class="me1">Name</span> & <span class="re0">@CrLf</span> & _<br /><span class="st0">"Display Name: "</span> & <span class="re0">$wbemObject</span>.<span class="me1">DisplayName</span> & <span class="re0">@CrLf</span> & _<br /><span class="st0">" Description: "</span> & <span class="re0">$wbemObject</span>.<span class="me1">Description</span> & <span class="re0">@CrLf</span> & _<br /><span class="st0">" Path Name: "</span> & <span class="re0">$wbemObject</span>.<span class="me1">PathName</span> & <span class="re0">@CrLf</span> & _<br /><span class="st0">" Start Mode: "</span> & <span class="re0">$wbemObject</span>.<span class="me1">StartMode</span> & <span class="re0">@CrLf</span> & _<br /><span class="st0">" State: "</span> & <span class="re0">$wbemObject</span>.<span class="me1">State</span> & <span class="re0">@CrLf</span> & <span class="re0">@CrLf</span> <span class="br0">)</span><br /><span class="kw1">Next</span></p></blockquote><p dir="ltr">如果我改用Get方法的话,我们会得到单独的对象,下面的代码是只显示Name为ALG的服务的相关信息:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><br /><span class="re0">$wbemServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2"</span><span class="br0">)</span><br /><br /><span class="re0">$wbemObjectSet</span> = <span class="re0">$wbemServices</span>.<span class="me1">Get</span><span class="br0">(</span><span class="st0">"Win32_Service.Name='ALG'"</span><span class="br0">)</span><br /><br /><span class="kw3">ConsoleWrite</span><span class="br0">(</span><span class="st0">"Name: "</span> & <span class="re0">$wbemObjectSet</span>.<span class="me1">Name</span> & <span class="re0">@CrLf</span> & _<br /> <span class="st0">"Display Name: "</span> & <span class="re0">$wbemObjectSet</span>.<span class="me1">DisplayName</span> & <span class="re0">@CrLf</span> & _<br /> <span class="st0">" Description: "</span> & <span class="re0">$wbemObjectSet</span>.<span class="me1">Description</span> & <span class="re0">@CrLf</span> & _<br /> <span class="st0">" Path Name: "</span> & <span class="re0">$wbemObjectSet</span>.<span class="me1">PathName</span> & <span class="re0">@CrLf</span> & _<br /> <span class="st0">" Start Mode: "</span> & <span class="re0">$wbemObjectSet</span>.<span class="me1">StartMode</span> & <span class="re0">@CrLf</span> & _<br /> <span class="st0">" State: "</span> & <span class="re0">$wbemObjectSet</span>.<span class="me1">State</span> & <span class="re0">@CrLf</span> & <span class="re0">@CrLf</span> <span class="br0">)</span></p></blockquote><p dir="ltr">在这两个例子中,后一个例子里的<span class="re0">$wbemObjectSet的意义等同于前一个例子里的<span class="re0">$wbemObject。</span></span></p><p dir="ltr"><span class="re0"><span class="re0">Get方法的格式如下:</span></span></p><p dir="ltr"><span class="re0"><span class="re0">SwbemServices.Get([strObjectPath][.KeyProperty='Value'])</span></span></p><p dir="ltr"><span class="re0"><span class="re0">strObjectPath是类的名字,</span></span><span class="re0"><span class="re0">KeyProperty是主键属性名,</span></span><span class="re0"><span class="re0">Value是指定的主键属性值。需要注意的是,你要获取的对象的KeyProperty='Value'必须有别于其他对象,否则就会出错。比如下面的代码就无法正常运行:</span></span></p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0"><span class="re0"><span class="re0"><span class="re0">$wbemServices</span>.<span class="me1">Get</span><span class="br0">(</span><span class="st0">"Win32_Service.State ='Stopped'"</span><span class="br0">)</span></span></span></span></p></blockquote></blockquote><p dir="ltr">方法4.直接用用moniker名字法</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr">如果你仔细阅读过第4节的话,应该会发现用moniker名字法不但能建立命名空间,还可以获取类和单独的实例。</p><p dir="ltr">具体语法我就不再复述了,下面是两个范例:</p><p dir="ltr">1.获取Win32_Service类</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$wbemObjectSet</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2:Win32_Service"</span><span class="br0">)</span></p></blockquote><p dir="ltr">2.获取Win32_Service类下Name属性为winmgmt的对象</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$wbemObject</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2:Win32_Service.name='winmgmt'"</span><span class="br0">)</span></p></blockquote></blockquote><p dir="ltr"><strong>六、深入了解命名空间</strong></p><p dir="ltr">1.管理脚本的默认命名空间</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr">默认情况下,我们用下面的代码就能连接到root\cimv2命名空间:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><br /><span class="re0">$wbemServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> <span class="br0">)</span></p></blockquote><p dir="ltr">这段代码没有指定目标命名空间,则脚本连接到由下列注册表设置识别的命名空间:</p><p dir="ltr">HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WBEM\Scripting\Default 命名空间</p><p dir="ltr">命名空间root\cimv2被初始配置为脚本默认的命名空间;但是,默认的脚本命名空间可以很容易地进行更改。因此,我们应该始终在WMI 脚本中标识一个托管资源的命名空间,而不是采用默认设置:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><br /><span class="re0">$wbemServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2"</span><span class="br0">)</span></p></blockquote><p dir="ltr">如果我们想查看脚本的默认命名空间的话,可以用下面的代码:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><br /><span class="re0">$wbemServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2"</span><span class="br0">)</span><br /><br /><span class="re0">$colWMISettings</span> = <span class="re0">$wbemServices</span>.<span class="me1">InstancesOf</span><span class="br0">(</span><span class="st0">"Win32_WMISetting"</span><span class="br0">)</span><br /><br /><span class="kw1">For</span> <span class="re0">$objWMISetting</span> <span class="kw1">in</span> <span class="re0">$colWMISettings</span><br /><span class="kw3">ConsoleWrite</span><span class="br0">(</span><span class="st0">"Default namespace for scripting: "</span> & _<br /><span class="re0">$objWMISetting</span>.<span class="me1">ASPScriptDefaultNamespace</span> & <span class="re0">@CrLf</span> <span class="br0">)</span><br /><span class="kw1">Next</span></p></blockquote><p dir="ltr">同样的,你还可以用下面的代码来设置默认的命名空间:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><br /><span class="re0">$wbemServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2"</span><span class="br0">)</span><br /><br /><span class="kw1">For</span> <span class="re0">$objWMISetting</span> <span class="kw1">in</span> <span class="re0">$colWMISettings</span><br /><span class="re0">$objWMISetting</span>.<span class="me1">ASPScriptDefaultNamespace</span> = <span class="st0">"root\cimv2"</span><br /><span class="re0">$objWMISetting</span>.<span class="me1">Put_</span><br /><span class="kw1">Next</span></p></blockquote></blockquote><p dir="ltr">2.列出命名空间</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr">读到这里,我们仅仅了解到root\cimv2这一个命名空间,不过通过WMI自身我们也能知道其他的命名空间。</p><p dir="ltr">WMI的命名空间信息可以通过__NAMESPACE类下的实例搜索到,下面的例子是用来搜索所有root\...形式的命名空间:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$objServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root"</span><span class="br0">)</span><br /><span class="re0">$colNameSpaces</span> = <span class="re0">$objServices</span>.<span class="me1">InstancesOf</span><span class="br0">(</span><span class="st0">"__NAMESPACE"</span><span class="br0">)</span><br /><br /><span class="kw1">For</span> <span class="re0">$objNameSpace</span> <span class="kw1">In</span> <span class="re0">$colNameSpaces</span><br /><span class="kw3">ConsoleWrite</span><span class="br0">(</span> <span class="re0">$objNameSpace</span>.<span class="me1">Name</span> & <span class="re0">@CrLf</span> <span class="br0">)</span><br /><span class="kw1">Next</span></p></blockquote><p dir="ltr">你可能已经注意到,上面的代码不提供目标计算机上所有可用的命名空间的完整描述。它只检索并显示在单一的、指定命名空间下的命名空间。为了在本地或远程的启用 WMI 的计算机上回显所有命名空间,我们可以通过递归来连接到并枚举每个命名空间:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="kw5">#include</span> <array.<span class="me1">au3</span>><br /><span class="kw1">Dim</span> <span class="re0">$strCsvListOfNamespaces</span><br /><br />EnumNameSpaces<span class="br0">(</span><span class="st0">"root"</span>, <span class="re0">$strCsvListOfNamespaces</span><span class="br0">)</span><br /><br /><span class="re0">$arrNamespaces</span> = <span class="kw3">StringSplit</span><span class="br0">(</span><span class="re0">$strCsvListOfNamespaces</span>, <span class="st0">","</span><span class="br0">)</span><br /><br /><span class="kw4">_ArrayDisplay</span><span class="br0">(</span><span class="re0">$arrNamespaces</span><span class="br0">)</span><br /><br /><span class="kw1">Func</span> EnumNamespaces<span class="br0">(</span><span class="re0">$strNamespace</span>, <span class="kw1">ByRef</span> <span class="re0">$tmpCsvListOfNamespaces</span><span class="br0">)</span><br /><br /><span class="kw1">If</span> <span class="re0">$tmpCsvListOfNamespaces</span> = <span class="st0">""</span> <span class="kw1">Then</span><br /><span class="re0">$tmpCsvListOfNamespaces</span> = <span class="re0">$strNamespace</span><br /><span class="kw1">Else</span><br /><span class="re0">$tmpCsvListOfNamespaces</span> = <span class="re0">$tmpCsvListOfNamespaces</span> & <span class="st0">","</span> & <span class="re0">$strNamespace</span><br /><span class="kw1">EndIf</span><br /><br /><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><span class="re0">$objWMIService</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\"</span> & <span class="re0">$strNameSpace</span><span class="br0">)</span><br /><br /><span class="kw1">If</span> <span class="kw1">not</span> <span class="re0">@error</span> <span class="kw1">Then</span><br /> <br /><span class="re0">$colNameSpaces</span> = <span class="re0">$objWMIService</span>.<span class="me1">InstancesOf</span><span class="br0">(</span><span class="st0">"__NAMESPACE"</span><span class="br0">)</span><br /><br /><span class="kw1">For</span> <span class="re0">$objNameSpace</span> <span class="kw1">In</span> <span class="re0">$colNameSpaces</span><br />EnumNamespaces<span class="br0">(</span><span class="re0">$strNameSpace</span> & <span class="st0">"\"</span> & <span class="re0">$objNameSpace</span>.<span class="me1">Name</span>, <span class="re0">$tmpCsvListOfNamespaces</span><span class="br0">)</span><br /><span class="kw1">Next</span><br /><span class="kw1">Else</span><br /><span class="re0">$tmpCsvListOfNamespaces</span>=<span class="st0">""</span><br /><span class="kw1">EndIf</span><br /><br /><span class="kw1">EndFunc</span></p></blockquote></blockquote><p dir="ltr">3.列出类</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr">下面的代码列出了所有在root\cimv2命名空间中定义的类:</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><br /><span class="re0">$wbemServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2"</span><span class="br0">)</span><br /><br /><span class="re0">$colClasses</span> = <span class="re0">$wbemServices</span>.<span class="me1">SubclassesOf</span><span class="br0">(</span><span class="br0">)</span><br /><br /><span class="kw1">For</span> <span class="re0">$objClass</span> <span class="kw1">In</span> <span class="re0">$colClasses</span><br /><span class="kw3">ConsoleWrite</span><span class="br0">(</span> <span class="re0">$objClass</span>.<span class="me1">Path_</span>.<span class="me1">Path</span> & <span class="re0">@CrLf</span> <span class="br0">)</span><br /><span class="kw1">Next</span></p></blockquote></blockquote><p dir="ltr">4.列出指定对象的属性</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr">下面的代码列出了Win32_Service类下的实例能使用的属性(还记得上面的那个列出服务的代码吗?里面所使用的属性可以这样查到):</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><span class="re0">$strComputer</span> = <span class="st0">"."</span><br /><span class="re0">$strClass</span> = <span class="st0">"Win32_Service"</span><br /><br /><span class="re0">$wbemServices</span> = <span class="kw3">ObjGet</span><span class="br0">(</span><span class="st0">"winmgmts:\\"</span> & <span class="re0">$strComputer</span> & <span class="st0">"\root\cimv2"</span><span class="br0">)</span><br /><br /><span class="re0">$objClass</span> = <span class="re0">$wbemServices</span>.<span class="me1">Get</span><span class="br0">(</span><span class="re0">$strClass</span><span class="br0">)</span><br /><br /><span class="kw1">For</span> <span class="re0">$objProperty</span> <span class="kw1">in</span> <span class="re0">$objClass</span>.<span class="me1">Properties_</span><span class="br0">(</span><span class="br0">)</span> <span class="co0">; Must use (), because method ends with an underscore</span><br /><span class="kw3">ConsoleWrite</span> <span class="br0">(</span><span class="re0">$objProperty</span>.<span class="me1">Name</span>& <span class="re0">@CrLf</span> <span class="br0">)</span><br /><span class="kw1">Next</span></p></blockquote></blockquote><p dir="ltr"><strong>七、WMI编程常用资源</strong></p><p dir="ltr">1.AutoIt Script-o-matic</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr">你可以在<a href="http://www.autoitscript.com/forum/index.php?automodule=downloads&showfile=29">这里</a>下载到这个工具。这个工具能够列出指定命名空间下的全部类,并显示出该类的全部属性。你还能用这个工具导出AU3脚本。</p></blockquote><p dir="ltr">2.MSDN</p><blockquote dir="ltr" style="margin-right: 0px"><p dir="ltr"><a href="http://www.microsoft.com/technet/scriptcenter/tools/scripto2.mspx">Scriptomatic 2.0</a> 官方的WMI查询工具</p><p dir="ltr"><a href="http://msdn2.microsoft.com/en-us/library/aa394572.aspx">WMI Reference</a> WMI的全部信息</p><p dir="ltr"><a href="http://msdn2.microsoft.com/en-us/library/aa392902.aspx">Querying with WQL</a> WQL查询语法</p><p dir="ltr"><a href="http://msdn2.microsoft.com/en-us/library/aa394585.aspx">WMI Tasks for Scripts and Applications</a> 官方WMI范例</p></blockquote> |