wmi Cookbook(翻译)

danny posted @ 2014年4月01日 16:49 in python with tags python windows WMI , 3467 阅读

WMI是什么

Windows管理规范(WMI)是Microsoft基于Web的企业管理(WBEM)的实现,这是一个行业计划,为有关计算机系统的几乎任何信息提供了一个公用信息模型(CIM)。

Python WMI模块是在pywin32扩展之上的轻量级封装,并隐藏了一些Python需要调用WMI API的凌乱管道。这是纯粹的Python, 应该兼容从2.1后(list comprehensions)任何版本Python及任何新版本的pywin32。

下载: https://pypi.python.org/pypi/WMI/#downloads

源地址: http://timgolden.me.uk/python/wmi/cookbook.html

  • WMI食谱
    概述
    示例
    列出所有正在运行的进程
    列出所有正在运行的记事本进程
    创建,然后摧毁一个新的记事本程序
    显示界面创建Win32_Process类的方法
    显示所有不在运行的自动服务
    显示每个固定磁盘的空闲空间百分比
    运行记事本,当它关闭时显示其文本
    监视新的打印作业
    重启远程计算机
    显示启用了IP的网络接口(适配器或者网卡)的IP地址和MAC地址
    什么程序自动启动,从哪里启动?
    查看在事件日志中的错误
    列出注册表项
    添加一个新的注册表项
    添加一个新的注册表值
    创建一个新的IIS站点
    显示共享驱动器
    显示打印作业
    显示磁盘分区
    安装软件
    以指定用户连接到另一台机器
    显示一个方法的签名
    计划作业
    最小化运行进程
    查找驱动器类型
    列出命名空间
    在线程中使用WMI
    监控多台机器的电源事件
    查找当前壁纸
     

wmi Cookbook

 

概述

These examples assume you are using the WMI module from this site. The following are examples of useful things that could be done with this module on win32 machines. It hardly scratches the surface of WMI, but that’s probably as well.

The following examples, except where stated otherwise, all assume that you are connecting to the current machine. To connect to a remote machine, simply specify the remote machine name in the WMI constructor, and by the wonders of DCOM, all should be well:

import wmi
c = wmi.WMI ("some_other_machine")

Note

The examples are designed to be complete and can be cut-and-pasted straight into a .py file, or even onto an open Python interpreter window (at least running under CMD on Win2000; that’s how I test them). Just select the code, including the final blank line, right-click [Copy], select your Python interpreter window, and right-click.

示例

 

列出所有正在运行的进程

import wmi
c = wmi.WMI ()

for process in c.Win32_Process ():
  print process.ProcessId, process.Name

列出所有正在运行的记事本进程

import wmi
c = wmi.WMI ()

for process in c.Win32_Process (name="notepad.exe"):
  print process.ProcessId, process.Name

创建,然后摧毁一个新的记事本程序

import wmi
c = wmi.WMI ()

process_id, return_value = c.Win32_Process.Create (CommandLine="notepad.exe")
for process in c.Win32_Process (ProcessId=process_id):
  print process.ProcessId, process.Name

result = process.Terminate ()

显示界面 .Creat Win32_Process类的方法

The wmi module tries to take the hard work out of WMI methods by querying the method for its in and out parameters, accepting the in parameters as Python keyword params and returning the output parameters as an tuple return value. The function which is masquerading as the WMI method has a __doc__ value which shows the input and return values.

import wmi
c = wmi.WMI ()

print c.Win32_Process.Create

显示所有不在运行的自动服务

import wmi
c = wmi.WMI ()

stopped_services = c.Win32_Service (StartMode="Auto", State="Stopped")
if stopped_services:
  for s in stopped_services:
    print s.Caption, "service is not running"
else:
  print "No auto services stopped"

显示每个固定磁盘的空闲空间百分比

import wmi
c = wmi.WMI ()

for disk in c.Win32_LogicalDisk (DriveType=3):
  print disk.Caption, "%0.2f%% free" % (100.0 * long (disk.FreeSpace) / long (disk.Size))

运行记事本,当它关闭时显示其文本

Note

This is an example of running a process and knowing when it’s finished, not of manipulating text typed into Notepad. So I’m simply relying on the fact that I specify what file notepad should open and then examining the contents of that afterwards.

This one won’t work as shown on a remote machine because, for security reasons, processes started on a remote machine do not have an interface (ie you can’t see them on the desktop). The most likely use for this sort of technique on a remote server to run a setup.exe and then, say, reboot once it’s completed.

import wmi
c = wmi.WMI ()

filename = r"c:\temp\temp.txt"
process = c.Win32_Process
process_id, result = process.Create (CommandLine="notepad.exe " + filename)
watcher = c.watch_for (
  notification_type="Deletion",
  wmi_class="Win32_Process",
  delay_secs=1,
  ProcessId=process_id
)

watcher ()
print "This is what you wrote:"
print open (filename).read ()

监视新的打印作业

import wmi
c = wmi.WMI ()

print_job_watcher = c.Win32_PrintJob.watch_for (
  notification_type="Creation",
  delay_secs=1
)

while 1:
  pj = print_job_watcher ()
  print "User %s has submitted %d pages to printer %s" % \
    (pj.Owner, pj.TotalPages, pj.Name)

重启远程计算机

Note

To do something this drastic to a remote system, the WMI script must take RemoteShutdown privileges, which means that you must specify them in the connection moniker. The WMI constructor allows you to pass in an exact moniker, or to specify the parts of it that you need. Use help on wmi.WMI.__init__ to find out more.

import wmi
# other_machine = "machine name of your choice"
c = wmi.WMI (computer=other_machine, privileges=["RemoteShutdown"])

os = c.Win32_OperatingSystem (Primary=1)[0]
os.Reboot ()

显示启用了IP的网络接口(适配器或者网卡)的IP地址和MAC地址

import wmi
c = wmi.WMI ()

for interface in c.Win32_NetworkAdapterConfiguration (IPEnabled=1):
  print interface.Description, interface.MACAddress
  for ip_address in interface.IPAddress:
    print ip_address
  print

什么程序自动启动,从哪里启动?

import wmi
c = wmi.WMI ()

for s in c.Win32_StartupCommand ():
  print "[%s] %s <%s>" % (s.Location, s.Caption, s.Command)

查看在事件日志中的错误

import wmi
c = wmi.WMI (privileges=["Security"])

watcher = c.watch_for (
  notification_type="Creation",
  wmi_class="Win32_NTLogEvent",
  Type="error"
)
while 1:
  error = watcher ()
  print "Error in %s log: %s" %  (error.Logfile, error.Message)
  # send mail to sysadmin etc.

列出注册表项

Note

This example and the ones below use the convenience function Registry() which was added to the wmi package in its early days. It’s exactly equivalent to:

import wmi
r = wmi.WMI (namespace="DEFAULT").StdRegProv
import _winreg
import wmi

r = wmi.Registry ()
result, names = r.EnumKey (
  hDefKey=_winreg.HKEY_LOCAL_MACHINE,
  sSubKeyName="Software"
)
for key in names:
  print key

添加一个注册表项

import _winreg
import wmi

r = wmi.Registry ()
result, = r.CreateKey (
  hDefKey=_winreg.HKEY_LOCAL_MACHINE,
  sSubKeyName=r"Software\TJG"
)

添加一个注册表新值

import _winreg
import wmi

r = wmi.Registry ()
result, = r.SetStringValue (
  hDefKey=_winreg.HKEY_LOCAL_MACHINE,
  sSubKeyName=r"Software\TJG",
  sValueName="ApplicationName",
  sValue="TJG App"
)

创建一个新的IIS站点

import wmi
c = wmi.WMI (namespace="MicrosoftIISv2")

#
# Could as well be achieved by doing:
#  web_server = c.IISWebService (Name="W3SVC")[0]
#
for web_server in c.IIsWebService (Name="W3SVC"):
  break

binding = c.new ("ServerBinding")
binding.IP = ""
binding.Port = "8383"
binding.Hostname = ""
result, = web_server.CreateNewSite (
  PathOfRootVirtualDir=r"c:\inetpub\wwwroot",
  ServerComment="My Web Site",
  ServerBindings= [binding.ole_object]
)

显示共享磁盘

import wmi
c = wmi.WMI ()

for share in c.Win32_Share ():
  print share.Name, share.Path

显示打印作业

Note

This page at Microsoft is quite a good starting point for handling printer matters with WMI.

import wmi
c = wmi.WMI ()

for printer in c.Win32_Printer ():
  print printer.Caption
  for job in c.Win32_PrintJob (DriverName=printer.DriverName):
    print "  ", job.Document
  print

显示磁盘分区

import wmi
c = wmi.WMI ()

for physical_disk in c.Win32_DiskDrive ():
  for partition in physical_disk.associators ("Win32_DiskDriveToDiskPartition"):
    for logical_disk in partition.associators ("Win32_LogicalDiskToPartition"):
      print physical_disk.Caption, partition.Caption, logical_disk.Caption

安装软件

Note

Example is after a post by Roger Upole to the python-win32 mailing list

import wmi
c = wmi.WMI ()

c.Win32_Product.Install (
  PackageLocation="c:/temp/python-2.4.2.msi",
  AllUsers=False
)

以指定用户连接到另一台机器

Note

You cannot connect to your own machine this way, no matter how hard you try to obfuscate the server name.

import wmi

#
# Using wmi module before 1.0rc3
#
connection = wmi.connect_server (
  server="other_machine",
  user="tim",
  password="secret"
)
c = wmi.WMI (wmi=connection)

#
# Using wmi module at least 1.0rc3
#
c = wmi.WMI (
  computer="other_machine",
  user="tim",
  password="secret"
)

显示一个方法的签名

import wmi
c = wmi.WMI ()
for opsys in c.Win32_OperatingSystem ():
  break

print opsys.Reboot
print opsys.Shutdown

计划作业

Note

The WMI ScheduledJob class correponds to the AT Windows service (controlled through the “at” command). As far as I know, it is not related to the Scheduled Tasks mechanism, controlled by a control panel applet.

import os
import wmi

c = wmi.WMI ()
one_minutes_time = datetime.datetime.now () + datetime.timedelta (minutes=1)
job_id, result = c.Win32_ScheduledJob.Create (
  Command=r"cmd.exe /c dir /b c:\ > c:\\temp.txt",
  StartTime=wmi.from_time (one_minutes_time)
)
print job_id

for line in os.popen ("at"):
  print line

最小化运行进程

Note

Thanks to Keith Veleba for providing the question and code which prompted this example

import wmi

SW_SHOWMINIMIZED = 1

c = wmi.WMI ()
startup = c.Win32_ProcessStartup.new (ShowWindow=SW_SHOWMINIMIZED)
pid, result = c.Win32_Process.Create (
  CommandLine="notepad.exe",
  ProcessStartupInformation=startup
)
print pid

查找驱动器类型

import wmi

DRIVE_TYPES = {
  0 : "Unknown",
  1 : "No Root Directory",
  2 : "Removable Disk",
  3 : "Local Disk",
  4 : "Network Drive",
  5 : "Compact Disc",
  6 : "RAM Disk"
}

c = wmi.WMI ()
for drive in c.Win32_LogicalDisk ():
  print drive.Caption, DRIVE_TYPES[drive.DriveType]

列出命名空间

import wmi

def enumerate_namespaces (namespace=u"root", level=0):
  print level * "  ", namespace.split ("/")[-1]
  c = wmi.WMI (namespace=namespace)
  for subnamespace in c.__NAMESPACE ():
    enumerate_namespaces (namespace + "/" + subnamespace.Name, level + 1)

enumerate_namespaces ()

在线程中使用WMI

Note

Note the use of pythoncom.Co(Un)initialize. WMI is a COM-based technology, so to use it in a thread, you must init the COM threading model. This applies also if you’re running in a service, for example, which is implicitly threaded.

import pythoncom
import wmi
import threading
import time

class Info (threading.Thread):
  def __init__ (self):
    threading.Thread.__init__ (self)
  def run (self):
    print 'In Another Thread...'
    pythoncom.CoInitialize ()
    try:
      c = wmi.WMI ()
      for i in range (5):
        for process in c.Win32_Process ():
          print process.ProcessId, process.Name
        time.sleep (2)
    finally:
      pythoncom.CoUninitialize ()

if __name__ == '__main__':
  print 'In Main Thread'
  c = wmi.WMI ()
  for process in c.Win32_Process ():
    print process.ProcessId, process.Name
  Info ().start ()

监控多台机器的电源事件

This is a demonstration of extrinsic events, threading and remote monitoring... all in one small package! The idea is that the power subsystem generates extrinsic events via its WMI provider whenever a machine enters or leaves suspend mode. Extrinsic events are useful because WMI doesn’t have to poll for them so you shouldn’t miss any. The multiple machines was just a practical example of using threads.

Note

Note the use of CoInitialize and CoUninitialize in the thread control code. Note also the simplified use of_wmi_class.watch_for() which will work for intrinsic and extrinsic events transparently.

import pythoncom
import wmi
import threading
import Queue

class Server (threading.Thread):

  def __init__ (self, results, server, user, password):
    threading.Thread.__init__ (self)
    self.results = results
    self.server = server
    self.user = user
    self.password = password
    self.setDaemon (True)

  def run (self):
    pythoncom.CoInitialize ()
    try:
      #
      # If you don't want to use explicit logons, remove
      # the user= and password= params here and ensure
      # that the user running *this* script has sufficient
      # privs on the remote machines.
      #
      c = wmi.WMI (self.server, user=self.user, password=self.password)
      power_watcher = c.Win32_PowerManagementEvent.watch_for ()
      while True:
        self.results.put ((self.server, power_watcher ()))
    finally:
      pythoncom.CoUninitialize ()

#
# Obviously, change these to match the machines
# in your network which probably won't be named
# after Harry Potter characters. And which hopefully
# use a less obvious admin password.
#
servers = [
  ("goyle", "administrator", "secret"),
  ("malfoy", "administrator", "secret")
]
if __name__ == '__main__':
  power_events = Queue.Queue ()
  for server, user, password in servers:
    print "Watching for", server
    Server (power_events, server, user, password).start ()

  while True:
    server, power_event = power_events.get ()
    print server, "=>", power_event.EventType

查找当前壁纸

import wmi
import win32api
import win32con

c = wmi.WMI ()
full_username = win32api.GetUserNameEx (win32con.NameSamCompatible)
for desktop in c.Win32_Desktop (Name=full_username):
  print \
    desktop.Wallpaper or "[No Wallpaper]", \
    desktop.WallpaperStretched, desktop.WallpaperTiled

 


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter