使用Python玩转WMI

429 查看

最近在网上搜索Python和WMI相关资料时,发现大部分文章都千篇一律,并且基本上只说了很基础的使用,并未深入说明如何使用WMI。本文打算更进一步,让我们使用Python玩转WMI。

1 什么是WMI

具体请看微软官网对WMI的介绍。这里简单说明下,WMI的全称是Windows Management Instrumentation,即Windows管理规范。它是Windows操作系统上管理数据和操作的基础设施。我们可以使用WMI脚本或者应用自动化管理任务等。

Using WMI可以知道WMI支持如下语言:

Application language Topic
Scripts written in Microsoft ActiveX script hosting, including Visual Basic Scripting Edition (VBScript) and Perl Scripting API for WMI.

Start with Creating a WMI Script.

For script code examples, see WMI Tasks for Scripts and Applications and the TechNet ScriptCenter Script Repository.

Windows PowerShell Getting Started with Windows PowerShell

WMI PowerShell Cmdlets, such as Get-WmiObject.

Visual Basic applications Scripting API for WMI.
Active Server Pages Scripting API for WMI.

Start with Creating Active Server Pages for WMI.

C++ applications COM API for WMI.

Start with Creating a WMI Application Using C++ and WMI C++ Application Examples (contains examples).

.NET Framework applications written in C#, Visual Basic .NET, or J# Classes in the Microsoft.Management.Infrastructure namespace. (The System.Management namespace is no longer supported). For more information, see WMI .NET Overview.

很遗憾,WMI并不原生支持Python。不过没有关系,它支持VB,而Python中的两个第三方库wmi和win32com,均能以类似VB的用法来使用。那么接下来,我们来讲讲如何使用。

 

2 使用WMI

2.1 使用wmi库操作WMI

以下是一个遍历所有进程,所有服务的示例:

可以看到,使用起来非常简单。但是有两个问题:一是wmi库实在是太慢了,能不能快点?二是如何知道例子中process和service有哪些属性(比如ProcessId等)?由于wmi库是动态生成底层执行语句,用dir(process)这种方式是获取不到ProcessId这种属性的。

针对第一个问题,我们可以使用win32com这个库来解决,它相较于wmi的速度快了很多。而第二个问题,先卖个关子,后文会有介绍。

2.2 使用win32com库操作WMI

win32com能模仿VB的行为,想了解如何使用win32com来操作WMI,最直接的方式是了解如何使用VB来操作WMI。在微软的官网上提供了很多现成的例子:WMI Tasks: ProcessesWMI Tasks: Services

其中一个例子关于进程是这样的:

它做了这样一件事:首先通过GetObject连接到Win32_Process所在的名称空间,然后执行WQL语句(类似SQL的查询语句)查到所有的进程,再把每一个进程的相关信息打印出来。WQL的具体用法请见官网,这里不详细介绍。

那么用win32com就可以这么写(例子中打印的属性为了简便,就不像上面那么多啦):

看上去,VB和win32com的用法非常接近!那么当我们想要使用win32com对WMI进行操作时,就可以参考微软官网上VB的例子,然后比葫芦画瓢写出Python版的代码。

上例中,我们使用了查询函数ExecQuery来查询符合条件的内容,不过如果我们仅仅是想要获得所有的数据,而没有特定的限定条件,就可以使用更简单的方式——InstancesOf,那么就可以写成下面这样:

有读者可能会问,我们怎么知道自己想要了解的内容在哪个名称空间,我们应该获取哪个实例,又该获取实例中的哪些属性呢?

 

3 WMI的名称空间

使用下面的脚本可以获得当前计算机上的名称空间: