第14章 Windows管理规范

我们一直期望但是又害怕写这一章。Windows管理规范(Windows Management Instrumentation,WMI)可能是微软提供给管理员使用的最优秀的工具之一。但同时它也是这个公司曾经对我们造成过的最多问题的部分。 WMI可以从计算机中收集大量系统信息。但有时候这些信息不易看懂,另外文档也不够友好。在本章,我们将从PowerShell的角度介绍WMI,以及WMI的工作方式和一些不完美的地方,以便全面揭示你将会遇到的问题。

需要强调的是,WMI是一个外部技术;PowerShell仅仅与其接口交互而已。本章的重点将放在PowerShell如何与WMI交互,而不是WMI的底层实现机制。如果你不想深入探讨WMI,我们在本章结尾提供了一些建议。PowerShell已经在最大程度减少你需要与WMI交互的部分做出了改进。

14.1 WMI概要

典型的Windows计算机包含数万个管理信息,WMI会把这些收集并整理成一些尽可能通俗易懂的信息。

在最顶层,WMI被组织成命名空间(namespaces)。可以把命名空间想象为关联到特定产品或技术的一个文件夹。比如,“root\CIMv2”这个命名空间包含了所有Windows操作系统和计算机硬件信息。而“root\MicrosoftDNS”命名空间包含了所有关于DNS服务器(假设你已经把这个角色安装到计算机上)的信息。在客户端计算机上,“root\SecurityCenter”包含了关于防火墙、杀毒软件和反流氓软件这些工具的信息。

注意:

“root\SecurtityCenter”的内容根据你计算机上的已安装程序的情况而有所不同,新版本的Windows使用“root\SecurityCenter2”代替,这是其中一个WMI使人困惑的地方。

图14.1展示了通过微软管理控制台(Microsoft Management Console,MMC)的WMI控制单元在我本机上产生的一些命名空间。

在命名空间中,WMI被分成一系列的类,每个类是可用于WMI查询的管理单元。比如,在“root\SecurityCenter”中的“Antivirus-Product”类被设计用于保存反间谍软件的信息;在“root\CIMv2”中的“Win32_LogicalDisk”类被设计用于保存逻辑磁盘的信息。但是即使一个计算机上存在某个类,也不代表计算机实际上安装了这些对应的组件。比如“Win32_TapeDrive”类在所有的Windows版本上都存在,不管是否安装了磁带驱动程序。

图14.1 浏览WMI命名空间

注意:

再一次提醒,不是所有的计算机都包含相同的WMI命名空间或类。比如,新版本的Windows存在“Root\SecurityCenter2”命名空间,而不是“Root\SecurityCenter”命名空间;而前者在新版本的计算机中包含了所有信息。

下面看一下从“root\SecurityCenter2”中查询“AntiSpywareProduct”,你可以查看返回结果:

PS C:\> Get-CimInstance -Namespace root\securitycenter2 -ClassName antispyw areproduct  

注意:

此例要求PowerShell v3及以上版本,我们稍微介绍一下“Get-CimInstance”命令。

当你有一个或多个可管理组件时,你可以看到在对应的类中有相同数量的实例(instances)。一个实例代表了一个现实世界的事件。如果你的计算机只有一个单一的BIOS,那么在“root\CIMv2”中会有一个关于“Win32_BIOS”的实例。如果计算机安装了100个后台服务,你会看到100个“Win32_Service”的实例。请注意,在“root\CIMv2”中的类型一般以“Wim32_”(即使在64位系统中亦然)或“CIM_”(Common Information Model的缩写,是WMI建立的标准)开头。在其他命名空间中,这些类名前缀很少出现。还有一种情况是在多个命名空间中存在重复的类型,虽然很少。但在WMI中允许,因为每个命名空间实际上是一种有边界的容器。当你引用一个类时,你同时需要引用其命名空间,以便WMI知道从哪里找到对应的类,从而避免因为多个重名但不属于同一个命名空间的类造成混乱。

所有这些实例、类和其他不可名状的东西统称为WMI仓库(WMI repository)。在旧版本的Windows中,WMI仓库有时会损坏从而不可用,必须通过重建来恢复。但是从Win 7开始,这种情况越来越少见。

表面看上去,使用WMI十分简单:你只需要指出哪个类包含你要的信息,然后从WMI中查询类的实例,最后检查实例的属性得知其管理信息。有时候可能需要实例执行一个方法,从而启动一个动作(action)或开始一个配置变更(configuration change)。

14.2 关于WMI的坏消息

WMI在其大部分生命周期中(最近有所好转),微软都没有把过多的精力放在对其内部控制上。微软为WMI制定了一系列的编程标准,但是产品组或多或少把精力放在如何实现类和是否对其文档化。结果就是使得WMI变得混乱。

在“root\CIMv2”命名空间中,有些类提供了让你修改配置设置的方法(methods)。因为属性是只读的,意味着你必须使用方法来修改。如果对应的方法不存在,你就不能使用WMI来修改这些类。当IIS团队采用WMI(IIS第六版),它们针对大量的元素进行了并行类的实现。比如一个网站,可以用一个具有典型只读属性的类表示,但是同时也提供了第二个类用于修改属性。这种情况下很容易因为文档质量不佳而导致混乱,特别是IIS团队倾向于使用自身提供的工具。IIS团队已经放弃了把WMI作为管理接口的做法,并从v7.5开始把注意力集中在PowerShell Cmdlets上,并且用一个PSProvider类替代WMI。

微软从来没规定某个产品必须使用WMI,或者如果这个产品使用了WMI,必须公开WMI的每个可能的部分。微软的DHCP服务可以访问到WMI。正如旧版本的Windows服务器一样,你可以查询网卡的配置,但是不能查到连接速度,因为这些信息不支持通过WMI查询。同时,虽然大部分“Win32_”的类都有很好的文档支持,但其他命名空间下的类大部分都没有相关文档,WMI是不支持类搜索的,因此查找这些类对你来说就变得费时费力(在下节将告诉你如何减少这种影响)。

但是微软也对此进行了改善,微软正在努力使PowerShell Cmdlets尽可能完成更多的管理任务。比如,过去WMI仅用于某种特定的编程方式来重启远程计算机,这个方法由“Win32_OperatingSystem”类实现。而现在,PowerShell提供了名称为“Restart-Computer”的Cmdlet来实现。在某些情况下,Cmdlets内部会通过WMI实现,而无须直接调用WMI。Cmdlets能提供更一致的接口,并且这些接口大部分都有很好的文档支持。虽然WMI不会消失,但时不时,你还是需要在某些场景用 到WMI。

实际上,在PowerShell v3及后续版本中,你会留意到大量“CIM”命令,如图14.2所示(作为“Get-Command”输出的一部分)。在大部分情况下,这些命令都是对WMI的某些部分进行了封装,从而提供了以PowerShell为中心与WMI交互的方式。你可以像使用其他Cmdlet一样使用这些Cmdlet,包括对这些Cmdlet使用Help命令。这使使用这部分Cmdlet和使用其他PowerShell中的Cmdlet的体验变得一致,也便于隐藏一些底层的WMI的复杂性。

14.3 探索WMI

最佳的WMI入门恐怕是暂时抛开PowerShell并从WMI自身出发。这里我们使用来自于SAPIEN Technologies公司(http://www.sapien.com/downloads ,要求注册的免费软件)提供WMI探索工具来进行WMI研究。我们可以从这个工具中得到大部分所需的关于WMI的信息。当然,这个工作要求耐心和不少的浏览量——这并不是最佳方法,但是我们最终还是选择了这个工具。

首先你不需要安装工具。也就是说,它是绿色的,可以通过U盘等工具把软件保存到任何你需要的计算机上使用。由于每台计算机上的WMI命名空间和类都不尽相同,所以你需要把工具直接在准备查询的机器上运行,以便看到对应机器的WMI仓库。

图14.2 “CIM”命令在WMI类的包装

现在我们需要查询一组计算机并从中得知它们的图标间距设置。这个任务依赖于Windows桌面,并且是操作系统的核心部分,所以我们从“root\CIMv2”类开始,显示在WMI浏览器左侧的树型视图中(见图14.3)。单击命名空间并在右侧查看对应的类,我们知道需要“Desktop”这个关键字。滚动右侧窗口的滚动条,最终锁定“Win32_Desktop”并单击它。此时下方窗体将展示其对应明细,然后我们选择【属性】标签页并查看其内容。在大约三分之一的地方,找到“IconSpacing”,其值为整数。

显而易见,搜索引擎是查询所需类信息的另一种好方法。我们往往使用“WMI”作为“WMI图标间距”的前缀查询,一般在查看几个例子之后就可以找到大概位置。这些例子可能是与VBScript相关的,或者是类似C#或Visual Basic等.NET语言相关的。不过这不重要,因为我们只是在查找WMI类名称。 比如,我们在搜索引擎(例子使用Google)中查找“wmi icon spacing”,可能会首先显示http://stackoverflow.com/questions/202971/formula-or-api-for-calulating-desktop-icon-spacing-on-windows-xp 作为第一个结果。在这个网页中会有一些C#代码:

ManagementObjectSearcher searcher = new        ManagementObjectSearcher("root\\CIMV2","SELECT * FROM Win32_Desktop");  

图14.3 WMI浏览器

对此,我们并不知道是否有用,但是“Win32_Desktop”看上去像是个类名。接下来我们就要查询该类名,但这种查询不会在意是否存在相应文档。我们会在本章后续介绍一些关于文档的问题。

另外一个途径是使用PowerShell本身。比如,假设我们想知道一些关于磁盘的信息,那么需要从猜测合理的命名空间开始。但是我们已经知道“root\CIMv2”包含了所有OS核心和硬件设备的信息,所以可以使用下面的命令:

PS C:\> Get-WmiObject -Namespace root\CIMv2 -list | where name -like '*dis *'      NameSpace:ROOT\CIMv2 NameMethodsProperties ----    -------   ---------- Win32_DisplayConfiguration   {} {BitsPerPel,Caption,...} Win32_DisplayControllerConfigura... {} {BitsPerPixel,Caption,...}CIM_DiskSpaceCheck  {Invoke}    ...} CIM_DiscreteSensor  {SetPowerState, R... {AcceptableValues, Availability,... CIM_Display  {SetPowerState, R... {Availability, Caption,... CIM_DiskDrive{SetPowerState, R... {Availability, Capabilities,... Win32_DiskDrive       {SetPowerState, R... {Availability, BytesPerSector,... CIM_DisketteDrive     {SetPowerState, R... {Availability, Capabilities,... CIM_LogicalDisk {SetPowerState, R... {Access, Availability, BlockSize,...} Win32_LogicalDisk       {SetPowerState,  R... {Access, Availability, BlockSize,...} Win32_MappedLogicalDisk{SetPowerState, R...  {Access, Availability, BlockSize,...} CIM_DiskPartition{SetPowerState, R...  {Access, Availability, BlockSize,...} Win32_DiskPartition    {SetPowerState, R...  {Access, Availability, BlockSize,...} Win32_LogicalDiskRootDirectory       {} {GroupComponent, PartComponent}...Win32_DiskQuota     {} {DiskSpaceUsed, Limit,...} Win32_LogonSessionMappedDisk{} {Antecedent, Dependent}...CIM_LogicalDiskBasedOnPartition      {} {Antecedent, Dependent,...Win32_LogicalDiskToPartition {} {Antecedent, Dependent,...CIM_LogicalDiskBasedOnVolumeSet      {} {Antecedent, Dependent,...Win32_DiskDrivePhysicalMedia {} {Antecedent, Dependent}...CIM_RealizesDiskPartition     {} {Antecedent, Dependent,...Win32_DiskDriveToDiskPartition       {} {Antecedent, Dependent} Win32_OfflineFilesDiskSpaceLimit     {} {AutoCacheSizeInMB,...Win32_PerfFormattedData_Counters...  {} {Caption, Description,... Win32_PerfRawData_Counters_FileS...  {} {Caption, Description,... Win32_PerfFormattedData_Distribu...  {} {AckMessagesReceivedPersecond,... Win32_PerfRawData_DistributedRou...  {} {AckMessagesReceivedPersecond,... Win32_PerfFormattedData_MSDTC_Di... {} {AbortedTransactions,... Win32_PerfRawData_MSDTC_Distribu... {} {AbortedTransactions,Win32_PerfFormattedData_MSSQLSER...  {} {Caption, Description,... Win32_PerfRawData_MSSQLSERVER_SQ... {} {Caption, Description,... Win32_PerfFormattedData_PeerDist... {} {BITSBytesfromcache,... Win32_PerfRawData_PeerDistSvc_Br... {} {BITSBytesfromcache,... Win32_PerfFormattedData_PerfDisk... {} {AvgDiskBytesPerRead,... Win32_PerfRawData_PerfDisk_Logic... {} {AvgDiskBytesPerRead,... Win32_PerfFormattedData_PerfDisk... {} {AvgDiskBytesPerRead,... Win32_PerfRawData_PerfDisk_Physi... {} {AvgDiskBytesPerRead,...  

最终我们找到“Win32_LogicalDisk”。

注意:

这些以“CIM”开头的名字通常是基本类,所以我们不能直接使用。“Win32”版本的类是Windows特有的,并且这种前缀仅用于特定命名空间——其他空间不使用这种前缀命名方式。

14.4 选择你的武器:WMI或CIM

在PowerShell v3及后续版本中,有两种与WMI交互的方式。

  • 所谓的“WMI Cmdlets”,如“Get-WmiObject”和“Invoke-WmiMethod”——这些都是遗留命令,意味着它们依旧能工作,但是微软不会对它们进行后续开发投入。它们与远程过程调用(RPC)交互,也就是说,只有在防火墙支持状态审查时才能通过防火墙(实际上很难)。
  • 新版的“CIM Cmdlets”,如“Get-CimInstance”和“Invoke-CimMethod”——它们或多或少等价于旧版本的“WMI Cmdlets”,但是它们通过WS-MAN(由Windows远程管理服务实现)交互,替代原有的RPCs。这是微软的主方向,执行“Get-Command–noun CIM*”可以显示很多微软提供的这类命令的 功能。

毫无疑问,这些命令的后端同样是WMI,其差异在于如何交互和如何被使用。在没有安装PowerShell的旧版本系统中,或者没有启用Windows 远程管理功能的系统中,WMI Cmdlets依旧能工作(这个功能从Windows NT 4.0 SP3开始引入)。对于已经装有PowerShell和启用了Windows远程管理服务的新系统,CIM Cmdlets提供最佳体验——微软也会对其进行持续的功能及性能改进。

14.5 使用Get-WmiObject

通过“Get-WmiObject” Cmdlet,你可以指定一个命名空间、一个类名甚至远程计算机的名称和其他凭据名。如果需要,还可以从指定的计算机中查询该类的所有实例。

如果需要减少类实例的返回结果,甚至可以提供筛选条件来实现。可以使用下面的语法获取一个命名空间中的类列表:

Get-WmiObject -namespace root\cimv2 –list  

注意,命名空间名字使用的是反斜杠,不是斜杠。

也可以通过指定命名空间和类型查询一个类:

Get-WmiObject -namespace root\cimv2 -class win32_desktop  

其中“root\CIMv2”命名空间是Windows XP SP2及后续版本上的系统默认命名空间,所以如果你的类在这个命名空间中,可以不显式指定。同时,“-class”是位置参数,也就是说,如果你把类名放到第一个位置,它依旧能正常工作。

这里有两个例子,其中一个使用Gwmi别名代替完整的Cmdlet名:

PS C:\> Get-WmiObject win32_desktop  PS C:\> gwmi antispywareproduct -namespace root\securitycenter2  

动手实验: 从现在开始,你应该动手运行每个我们展示的命令。对于涉及远程计算机名称的,如果没有另外一台机器可供测试,可以用localhost替代。

对于许多WMI类,PowerShell的默认配置文件已经设定了需要展示的属性。“Win32_OperatingSystem”是一个很好的例子,因为它默认仅在列表中展示了6个属性。请记住,你总能把WMI对象用管道传输到“Gm”或“Format-List *”中,以便查看所有可用的属性。“Gm”总是列出所有可用的方法。请看例子:

PS C:\> Get-WmiObject win32_operatingsystem | gm    TypeName: System.Management.ManagementObject#root\cimv2\Win32_Operating System Name    MemberType  Definition ----    ----------  ---------- Reboot       Method      System.Managemen... SetDateTimeMethod       System.Managemen... Shutdown     Method      System.Managemen... Win32Shutdown       Method      System.Managemen... Win32ShutdownTracker       Method      System.Managemen... BootDevice   Property    System.String Bo... BuildNumber  Property    System.String Bu... BuildType    Property   System.String Bu... Caption       Property    System.String Ca... CodeSet      Property     System.String Co... CountryCode  Property    System.String Co... CreationClassName    Property     System.String Cr...  

为了节省空间,这里截断了部分输出结果。如果想看完整结果,请自行执行命令。

另外,“-filter”参数允许你通过指定的规则查询特定实例。这个参数有点棘手。这里有个例子,可以看出其最坏情况下的结果:

PS C:\> gwmi -class win32_desktop -filter "name='COMPANY\\Administrator'" __GENUS : 2 __CLASS : Win32_Desktop __SUPERCLASS   : CIM_Setting __DYNASTY       : CIM_Setting __RELPATH       : Win32_Desktop.Name="COMPANY\\Administrator" __PROPERTY_COUNT       : 21 __DERIVATION   : {CIM_Setting} __SERVER: SERVER-R2 __NAMESPACE  : root\cimv2 __PATH       : \\SERVER-R2\root\cimv2:Win32_Desktop.Name="COMPANY \\Administrator" BorderWidth  : 1 Caption       : CoolSwitch    : CursorBlinkRate      : 530 Description    : DragFullWindows       : False GridGranularity: IconSpacing    : 43 IconTitleFaceName      : Tahoma IconTitleSize  : 8 IconTitleWrap  : True Name   : COMPANY\Administrator Pattern : 0 ScreenSaverActive    : False ScreenSaverExecutable : ScreenSaverSecure     : ScreenSaverTimeout    : SettingID      : Wallpaper       : WallpaperStretched    : True WallpaperTiled : False  

对于这个命令和输出结果,有些事情是需要注意的:

  • 筛选条件通常被双引号包住。
  • 筛选比较操作符并不使用PowerShell的常规操作符“-eq”或“-like”。取而代之的是更加传统、更加编程化的操作符,比如=,>,<,<=,>=和<>。可以使用关键字“LIKE”作为操作符,但在匹配值时必须使用“%”作为字符通配符,如“NAME LIKE ‘%administrator%’”。注意,这里不能像PowerShell的其他地方一样使用*作为通配符。
  • 字符串匹配是以单引号包住,这也是筛选表达式的最外层的引号是双引号的 原因。
  • 避免在WMI中使用反斜杠。当你需要使用文本的反斜杠时,你必须使用两个反斜杠替代。
  • Gwmi的输出总会包含一个关于系统属性的数量值。PowerShell的默认显示配置通常会隐藏这个值,但是如果你执意列出所有属性或者这个类不属于默认配置范畴,这个数量值还是可以显示的。系统属性名以双下划线开始。这里有两个非常有用的属性:
__SERVER:包含被查询的实例所在的计算机名。当所查询的WMI信息来自于多台计算机时非常有用,这个属性来自于“PSComputerName”属性。__PATH:是实例本身的绝对应用。如果需要的话,可以用来查询实例。

这个Cmdlet不仅可以从远程计算机中查询信息,也可以从多台计算机中检索,使用一些技巧即可产生一个包含计算机名或IP地址的字符串集合。比如:

PS C:\> Gwmi Win32_BIOS -comp server-r2,server3,dc4  

计算机名按顺序连接,如果某一台计算机不可用,这个Cmdlet会产生一个错误,并跳过这台计算机,继续把后续的计算机连接起来。对于不可用的计算机,Cmdlet通常需要等待直到超时发生,意味着Cmdlet可能会暂停30~45秒之后才决定放弃这台计算机,然后产生错误并继续向后连接。

一旦你查询到一个WMI实例的集合后,可以把它们用管道连接到任何“-Object”Cmdlet、“Format-”Cmdlet或“Out-”、“Export-”或“ConvertTo-”Cmdlet中。你可以使用下面的例子定制表格显示“Win32_BIOS”类的信息:

PS C:\> Gwmi Win32_BIOS | Format-Table SerialNumber,Version –auto  

在第10章中,我们已经介绍了如何使用“Format-Table”Cmdlet来产生定制列。当你想从一个给定计算机中查询一些WMI类并集成到一个表时,该技术在这里就可以派上用场。此时你可以创建一个关于表的自定义列,并用列的表达式执行一个全新的WMI查询。语法如下,虽然看上去有点头大,但是结果却能让人满意。

PS C:\> gwmi -class win32_bios -computer server-r2,localhost | format-table   @{l='ComputerName';e={$_.__SERVER}},@{l='BIOSSerial';e={$_.SerialNumber}}, @{l='OSBuild';e={gwmi -class win32_operatingsystem -comp $_.__SERVER | sele  ct-object -expand BuildNumber}} -autosize  ComputerName BIOSSerial     OSBuild  ------------ ----------       --------  SERVER-R2    VMware-56 4d 45 fc 13 92 de c3-93 5c 40 6b 47 bb 5b 86 7600  

如果你把前面的语法复制到PowerShell ISE中,可以很容易编译并格式化:

gwmi -class win32_bios -computer server-r2,localhost |   format-table    @{l='ComputerName';e={$_.__SERVER}},   @{l='BIOSSerial';e={$_.SerialNumber}},   @{l='OSBuild';e={      gwmi -class win32_operatingsystem -comp $_.__SERVER |      select-object -expand BuildNumber}    } –autosize  

工作原理:

  • “Get-WmiObject”从两台计算机中查询“Win32_BIOS”信息。
  • 结果被管道传输到“Format-Table”。“Format-Table”被要求创建三个定制列:
  • 第一列:名称为ComputerName,使用“Win32_BIOS”实例中的“__SERVER”系统属性得出。第二列:名称为BIOSSerial,使用“Win32_BIOS”实例中的“SerialNumber”属性得出。第三列:名称为OSBuild。这列执行一个全新的“Get-WmiObject”查询,从“Win32_BIOS”实例的“__SERVER”属性中查询“Win32_OperatingSystem”类。然后把结果用管道传输到“Select-Object”中,这些信息来自于“Win32_OperatingSystem”实例的“BuildNumber”属性的内容,并用于OSBuild列的填充值。

语法有点复杂,但是提供了满意的结果。并且作为一个很好的例子展示了如何通过一些精心挑选的PowerShell Cmdlet实现你要的结果。

我们已经提醒过,一些WMI类包含方法。你可以在第16章中看到如何使用这些方法。这些方法相对难懂,所以独立出一章来介绍。

14.6 使用Get-CimInstance

Get-CimInstance是PowerShell v3引入的新命令,与“Get-WmiObject”有很多相似的地方,但是也有几个语法上的差异:

  • 你需要使用“-ClassName”代替“-Class”(虽然你只需要输入-Class,但是如果你只记住了该参数名称的话,这没有问题)。
  • 不存在用于列出命名空间中的所有类的“-List”参数。取而代之的是使用“Get-CimClass”并搭配“-Namespace”参数来获取类列表。
  • 没有“-Credential”参数;如果你需要从远程计算机查询并被要求提供替代凭据,需要通过“Invoke-Command”(前面章节已介绍)发送“Get-CimInstance”。比如:
PS C:\> Get-CimInstance -ClassName Win32_LogicalDisk  DeviceID   DriveType ProviderName     VolumeNameSize       FreeSpace  --------   ---------  ------------     ----------       ----       ---------  A:  2  C:  3 687173... 580806...  D:  5       HB1_CCPA_X64F... 358370... 0  

如果你需要使用替代凭据查询远程计算机,可以使用类似命令:

PS C:\> invoke-command -ScriptBlock { Get-CimInstance -ClassName win32_proc  ess } -ComputerName WIN8 -Credential DOMAIN\Administrator  

14.7 WMI文档

前面提到过,搜索引擎通常是查找已有WMI文档的最佳方式。虽然“Win32_”类在微软的MSDN网站上有很好的文档记录,但是搜索引擎依旧是查询正确页面的最容易的方式。你只需要把类名在Google或者Bing上搜索,通常第一条就会导航到http://msdn.microsoft.com/ 。

14.8 常见误区

在过去的10章里面介绍了如何使用内置的PowerShell帮助,所以你可能更倾向于在PowerShell中运行类似“help win32_service”的命令。不幸的是,在这里行不通。操作系统本身不包含任何WMI信息,所以PowerShell的帮助功能不能实现你的期望。你可能希望从网上的其他管理员和程序员分享的经验中而不是从微软信息中得到大部分你要的信息,比如查询“root\SecurityCenter”。不幸的是,你不会在结果中找哪怕一个微软的文档页。

WMI的筛选规则的差异也是其中一个误区。不管任何时候,你需要在所有可用实例中筛选信息时都应该提供过滤条件。但是别忘了,筛选语法是存在差异的。筛选语法是伴随WMI而不是由PowerShell处理,所以你必须使用WMI规定的语法去替代内置的PowerShell操作符。

另外一些在我们的学生中常见的关于WMI的误区是,虽然PowerShell提供了从WMI查询信息的简易途径,但是WMI并不集成在PowerShell中。WMI是一个外部技术,有自己的规则和工作方式。WMI虽然可以在PowerShell内部使用,但和其他Cmdlets不一样,因为这些Cmdlets完全集成在PowerShell中。所以请注意WMI的这些误区。

14.9 动手实验

注意:

对于本次动手实验来说,你需要运行PowerShell v3或更新版本PowerShell的计算机。

花点时间完成下面的动手任务。使用WMI的难处主要在于如何找到你所需要的类的信息,所以本实验中大部分时间会花在查找正确的类上面。尝试花点儿时间在思考关键字上(我们会给一些提示),并使用WMI explorer快速查找这些类(WMI Explorer把类按字母顺序排列,便于我们验证自己的猜测)。记住,PowerShell的帮助系统并不能帮助你查找WMI类。

1.使用什么类可以查看一个网卡的当前IP地址?这个类是否有什么方法可供发布DHCP租期?(提示:network是一个不错的关键字。)

2.创建一个显示计算机名、操作系统版本号、操作系统描述(标题)和BIOS序列号的表。(提示:你已经见过这个技术,但是你必须稍微反过来使用并且首先查询OS类,然后查询BIOS。)

3.使用WMI查询关于热修复补丁(hotfixes)的列表。(提示:微软通常把这些引用为quick fix engineering。)这个列表的内容是否和“Get-Hotfix”的结果不一致?

4.列出关于服务的列表,包含它们的当前状态、启动模式和启动账号信息。

5.能否找到一个类用于显示已安装的软件产品信息?你认为这个列表完整了吗?

动手实验: 当你完成这个实验后,尝试完成附录中的实验回顾2。

14.10 进一步学习

WMI是一个巨大的、复杂的技术,其中一些技术足以编写一整本书。实际上确实有人这样做了:PowerShell and WMI by fellow MVP Richard Siddaway(Manning, 2012)。这本书使用了大量例子,并讨论了关于PowerShell v3引入的CIM Cmdlets的新功能。如果谁有深入学习WMI的意愿,我强烈建议阅读这本书。

如果你发现WMI实在很难理解,别担心。这是正常反应。但是我们有一些好消息:在PowerShell v3及后续版本中,你可以轻易使用WMI而不用深入理解它。因为微软已经开发了数百个Cmdlets用于封装WMI。这些Cmdlets提供了帮助信息、可发现性、示例和所有其他好用的Cmdlets能提供给你的东西,但是它们的内核还是使用WMI。这样能更好地使用WMI的强大功能,又避免处理一些使人困惑的元素。


《Windows PowerShell 实战指南》