**什么是WMI** WMI可以从计算机中收集大量系统信息。但有时候这些信息不易看懂,另外文档也不够友好。WMI是一个外部技术,PowerShell仅仅与其接口进行交互而已。 在最顶层,WMI被组织成命名空间(namespaces)。可以把命名空间想象为关联到特定产品或技术的一个文件夹。比如,“root\CIMv2”,该命名空间包含了所有Windows操作系统和计算机硬件信息。而“root\MicrosoftDNS”命名空间包含了所有关于DNS服务器(假设你已经在计算机中安装了该角色)的信息。 在命名空间中,WMI被分成一系列的类,每个类都是可用于WMI查询的管理单元。比如,在“root\SecurityCenter”中的“Antivirus-Product”类被设计用于保存反间谍软件的信息;在“root\CIMv2”中的“Win32_LogicalDisk”类被设计用于保存逻辑磁盘的信息。但是即使一个计算机上存在某个类,也不代表计算机实际上安装了对应组件。比如无论是否安装了磁带驱动程序。“Win32_TapeDrive”类在所有的Windows版本上都存在。不是所有的计算机都包含相同的WMI命名空间或类。 **WMI的未来** 在WMI大部分生命周期中,微软都没有把过多的精力放在对其内部控制上(最近有所好转)。微软为WMI制定了一系列的编程标准,但是产品组或多或少把精力放在如何实现类和是否对其文档化。结果就是使得WMI变得混乱。 所谓的“WMI Cmdlets”,例如“Get-WmiObject”与“Invoke-WmiMethod”——这些都是遗留命令,意味着它们依旧能工作,但是微软不会对它们进行后续开发投入。它们与远程过程调用(RPC)交互,也就是说,只有在防火墙支持状态审查时才能通过防火墙(实际上很难)。 新版的“CIM Cmdlets”,例如“Get-CimInstance”与“Invoke-CimMethod”——它们或多或少等价于旧版本的“WMI Cmdlets”,但是它们通过WS-MAN(由Windows远程管理服务实现)交互,替代原有的RPCs。 在Windows Server 2012 R2以及更新版本中,旧版的WMI默认为禁用状态,因此尽可能使用CIM。除此之外,CIM cmdlet可以使用旧版的RPC(或DCOM)协议通讯,因此与老机器进行通讯时,你也可以仅使用CIM cmdlet。 在执行WMI筛选的时候,筛选语法是传递到WMI,而不是由PowerShell处理,所以你必须使用WMI规定的语法去替代内置的PowerShell操作符。 ``` Get-WmiObject win32_process -filter {name='notepad.exe'} |Invoke-WmiMethod -Name Terminate ``` **WMI的(微弱)优势** 虽然WMI所需的RPC网络通信难以穿透防火墙,但WMI能够适用的计算机数量最多(当前来说);CIM只需要更新更简单的WS-MAN通信,但在老版本的Windows默认情况下,并没有安装WS-MAN。 **WMI串行与并行执行** Get-WMIObject命令会与一台或多台远程计算机进行连接,但是通过串行方式实现,效率比较低。 备注:gwmi是Get-WMIObject的缩写 ``` gwmi -class win32_bios -computer server-r2,localhost | format-table @{label='ComputerName';expression={$_.__SERVER}}, @{label='BIOSSerial';expression={$_.SerialNumber}}, @{label='OSBuild';expression= {gwmi -class \win32_operatingsystem -computer $_.__SERVER | select-object -expand BuildNumber}} -autosize ``` 在-ScriptBlock参数(或者是该参数的别名,-Command)中指定的任意命令都会并行发送到指定的每台计算机。可以同时访问多达32台计算机(除非你修改了-ThrottleLimit参数允许同时访问更多或者更少的计算机),所以当你指定了超过32个计算机名称,仅有前32台计算机会开始执行该命令。当在前32台计算机即将结束时,剩余的计算机才可以开始执行这些命令。另外,当在所有计算机上都执行结束后,上层的父作业会返回一个完整的状态。 **备注:**Get-CimInstance是Get-WMIObject的新式写法 ``` invoke-command -ScriptBlock { Get-CimInstance -ClassName win32_process } -ComputerName WIN8 -Credential DOMAIN\Administrator ``` 备注:本文部分内容参考图书《powershell实战指南第三版》 更多内容请参考 ![](https://s1.51cto.com/images/blog/201909/18/ba1fade1361ec84370cb54c0738b3644.jpg?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)