您好,BM。正如您的电子邮件中所提到的那样,我们脚本专家总是告诉人们,在 WMI 中,您可以只用一个圆点 (.) 来引用本地计算机。例如,下面的小型脚本将您连接到本地计算机上的 WMI 服务:
strComputer = "."
Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")
酷吧?当然,正如您所指出的那样,这实际上只是故事的一半:是的,我们可以用一个圆点来引用本地计算机,但是如果我们需要知道该计算机的名称,该怎么办呢?当需要这样做的时候,如果它可帮助您确定该圆点所代表的计算机的名称,那么在这种情况下,脚本专家不会非常有帮助。
|
注意:老实说,这实际上听起来不像是脚本专家做了一半工作,然后就轻易地放弃了。通常我们在放弃某件事之前,不会做得那么多! |
在进行下一步之前,我们或许应该花一点时间,和听众中抱有怀疑态度的人讲一下。毫无疑问,你们中有些人正在一边看着这个问题,一边在想“这有什么大不了的?如果脚本是在本地计算机上运行,那么为什么还要关心本地计算机的名称呢?如果脚本正在远程运行,那么不是已经知道运行该脚本的计算机名称了吗?只将变量 strComputer 的值设置为该远程计算机的名称不就行了?”
所有上述问题的答案都是一样的:也许是。但我想再说一遍,也许不是。例如,假设我们的代码作为登录脚本或者计算机启动脚本的一部分运行,并且假设我们需要将所收集的数据记录到数据库。在上述的某种情况下,我们需要知道计算机的名称。是的,使用一个圆点代表计算机名称,脚本会运行得很好,但是我们不能完全依赖于圆点;如果我们那样做的话,数据库最终会如下所示:
|
计算机 |
处理器数目 |
|
. |
1 |
|
. |
2 |
|
. |
4 |
|
. |
1 |
很不错,但信息性不是太强。不用说,类似下面的表格会更有用一些:
|
计算机 |
处理器数目 |
|
atl-ws-01 |
1 |
|
atl-fs-02 |
2 |
|
atl-dc-03 |
4 |
|
atl-ws-04 |
1 |
同样,我们在处理远程计算机时,有时候确实需要得到计算机名称。使用 WMI,您可以通过指定计算机名称,连接到远程计算机;然而,您还可以通过指定 IP 地址,连接到远程计算机:
strComputer = "192.168.1.1"
Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")
因为很少有人记得所有计算机的 IP 地址(还因为,由于 DHCP 的缘故,许多 IP 地址无论如何会经常更改),此类表也仅仅是或多或少地有些作用:
|
计算机 |
处理器数目 |
|
192.168.1.1 |
1 |
|
192.168.1.2 |
2 |
|
192.168.1.3 |
4 |
|
192.168.1.4 |
1 |
换言之,甚至在这个高科技的时代,像名称这类过时的东西仍然可以派上用场。(这从躲在“脚本专家”这一共同名称之后的一群人口中说出来,听起来非常有趣,不是吗?)
那么,我们可以使用 WMI 确定本地计算机(或者,例如,我们只知道其 IP 地址的远程计算机)的名称吗?肯定可以这样做。如果我们告诉您有成百上千种不同的方法可以做到这一点,我们并不是在开玩笑。例如,假设您非常希望使用 Win32_BIOS 类确定计算机名称。好啊,为什么不试试:
strComputer = "."
Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_BIOS")
For Each objItem in colItems
Wscript.Echo objItem.Path_.Server
Next
正如您所看到的那样,这是一个标准的 WMI 脚本,它绑定到本地计算机上的 WMI 服务。然后,我们使用这行代码来检索该计算机的 BIOS 信息:
Set colItems = objWMIService.ExecQuery("Select * From Win32_BIOS")
我们为什么选择 Win32_BIOS 类?没有原因;我们本可以选择任何 WMI 类。这是因为每个 WMI 类都会返回一个 SWbemObjectPath 对象;该对象的 Path_ 属性充当所讨论项目的唯一地址。例如,计算机上 BIOS 的 Path_ 可能看起来与以下内容有点类似:
//ATL-WS-01/root/cimv2:Win32_BIOS.Name="EPP runtime BIOS - Version 1.1 ",
SoftwareElementID="EPP runtime BIOS - Version 1.1 ",SoftwareElementState=3,
TargetOperatingSystem=0,Version="HP - 22110520"
该路径是唯一的:计算机 atl-ws-01 上的其他对象不会有相同的路径。
正如您所看到的那样,计算机的名称 (ATL-WS-01) 已经嵌入到该路径的开头部分。(这说明:路径中不包括计算机名称,和地址“第 111 大街”中不包括城市名称一样有用。)无可否认,您可以执行一些复杂的字符串操作,来尝试从路径中挑出计算机名称。或者,我们仅要求获得 Server 属性的值,如下所示:
For Each objItem in colItems
Wscript.Echo objItem.Path_.Server
Next
就是这么简单。而且,首先,从脚本返回的任何 WMI 对象,都会包括 SWbemObjectPath 对象和 Server 属性。您准备好使用 Win32_ParallelPort 类连接到计算机了吗?好;如果准备好了,就可以使用 Win32_ParallelPort 获取 Server 属性的值:
strComputer = "."
Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_ParallelPort")
For Each objItem in colItems
Wscript.Echo objItem.Path_.Server
Next
使用 Win32_PrinterConfiguration 类连接到计算机?那么,您可以使用 Win32_PrinterConfiguration 获取 Server 属性的值。使用 Win32_LogicalDisk 类连接到计算机?那么,您便能够了解 - 嗯,您已领会了要旨。
但是,如果您不喜欢所有这些 SWbemObjectPaths 的谈话怎么办?嗯,在这种情况下,您可以始终依赖 Win32_ComputerSystem 类,来获取计算机名称:
strComputer = "."
Set objWMIService = GetObject("winmgmts://" & strComputer & "/root/cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_ComputerSystem")
For Each objItem in colItems
Wscript.Echo objItem.Name
Next
该脚本运行良好;没有比使用 Win32_TimeZone 类确定计算机名称更酷的了。想象一下您现在可能会赢多少场酒吧打赌;毕竟,从此以后您可以走进拥挤的酒吧对人们说:“给我 WMI 类的名称 - 任何 WMI 类 - 我就使用这个类来确定计算机的名称。”如果这并未给人们留下深刻印象,那么他们也许不值得您给其留下印象。
BM,我们希望以上能回答您的问题。毕竟,我们脚本专家为自己的座右铭而自豪:工作不要做一半。请注意,我们不必履行该格言。但是我们为它而骄傲。