wmi – Windows Management Instrumentation
Windows Management Instrumentation (WMI) is Microsoft’s answer to
the DMTF’s Common Information Model. It allows you to query just
about any conceivable piece of information from any computer which
is running the necessary agent and over which have you the
necessary authority.
Since the COM implementation doesn’t give much away to Python
programmers, I’ve wrapped it in some lightweight classes with
some getattr / setattr magic to ease the way. In particular:
The _wmi_namespace object itself will determine its classes
and allow you to return all instances of any of them by
using its name as an attribute:
disks = wmi.WMI ().Win32_LogicalDisk ()
In addition, you can specify what would become the WHERE clause
as keyword parameters:
fixed_disks = wmi.WMI ().Win32_LogicalDisk (DriveType=3)
The objects returned by a WMI lookup are wrapped in a Python
class which determines their methods and classes and allows
you to access them as though they were Python classes. The
methods only allow named parameters:
for p in wmi.WMI ().Win32_Process (Name="notepad.exe"):
p.Terminate (Result=1)
Doing a print on one of the WMI objects will result in its
GetObjectText_ method being called, which usually produces
a meaningful printout of current values.
The repr of the object will include its full WMI path,
which lets you get directly to it if you need to.
You can get the associators and references of an object as
a list of python objects by calling the associators () and
references () methods on a WMI Python object:
for p in wmi.WMI ().Win32_Process (Name="notepad.exe"):
for r in p.references ():
print r
Note
Don’t do this on a Win32_ComputerSystem object; it will
take all day and kill your machine!
WMI classes (as opposed to instances) are first-class
objects, so you can get hold of a class, and call
its methods or set up a watch against it:
process = wmi.WMI ().Win32_Process
process.Create (CommandLine="notepad.exe")
To make it easier to use in embedded systems and py2exe-style
executable wrappers, the module will not force early Dispatch.
To do this, it uses a handy hack by Thomas Heller for easy access
to constants.
Typical usage will be:
import wmi
vodev1 = wmi.WMI ("vodev1")
for disk in vodev1.Win32_LogicalDisk ():
if disk.DriveType == 3:
space = 100 * long (disk.FreeSpace) / long (disk.Size)
print "%s has %d%% free" % (disk.Name, space)
Many thanks, obviously to Mark Hammond for creating the win32all
extensions, but also to Alex Martelli and Roger Upole, whose
c.l.py postings pointed me in the right direction.
Thanks especially in release 1.2 to Paul Tiemann for his code
contributions and robust testing.
Exceptions
All COM-related exceptions are wrapped in x_wmi or one of its
subclasses. Therefore you can safely trap x_wmi as a root
exception.
From v1.4 onwards exceptions now contain the underlying COM error
(if any) as their x_wmi.com_error attribute:
import wmi
try:
c = wmi.WMI ("non-existent-machine")
except wmi.x_wmi, x: # Py3+ except wmi.x_wmi as x:
print "Exception number", x.com_error.hresult
-
exception wmi.x_wmi(info='', com_error=None)
Ancestor of all wmi-related exceptions. Keeps track of
an info message and the underlying COM error if any, exposed
as the com_error attribute.
-
exception wmi.x_wmi_invalid_query(info='', com_error=None)
Raised when a WMI returns wbemErrInvalidQuery
-
exception wmi.x_wmi_timed_out(info='', com_error=None)
Raised when a watcher times out
-
exception wmi.x_wmi_no_namespace(info='', com_error=None)
Raised when an attempt is made to query or watch
from a class without a namespace.
-
exception wmi.x_access_denied(info='', com_error=None)
Raised when WMI raises 80070005
-
exception wmi.x_wmi_authentication(info='', com_error=None)
Raised when an invalid combination of authentication properties is attempted when connecting
-
exception wmi.x_wmi_uninitialised_thread(info='', com_error=None)
Raised when WMI returns 800401E4 on connection, usually
indicating that no COM threading model has been initialised
Support Classes & Functions
These classes and functions are provided internally to the
module to support various operations internally. Certain of
them, in particular from_time() and to_time()
could well be used externally.
-
class wmi.SelfDeprecatingDict(dictlike)
Provides for graceful degradation of objects which
are currently dictionaries (and therefore accessed via
.keys, .items, etc.) into lists. Wraps an existing
dict and allows it to be addressed as a dict or as a
list during an interregnum, issuing a DeprecationWarning
if accessed as a dict.
-
class wmi.ProvideConstants(comobj)
When called on a win32com.client.Dispatch object,
provides lazy access to constants defined in the typelib.
They can then be accessed as attributes of the _constants
property. (From Thomas Heller on c.l.py).
-
wmi.handle_com_error(err=None)
Convenience wrapper for displaying all manner of COM errors.
Raises a x_wmi exception with more useful information attached
Parameters: | err – The structure attached to a pywintypes.com_error |
-
wmi.from_time(year=None, month=None, day=None, hours=None, minutes=None, seconds=None, microseconds=None, timezone=None)
Convenience wrapper to take a series of date/time elements and return a WMI time
of the form yyyymmddHHMMSS.mmmmmm+UUU. All elements may be int, string or
omitted altogether. If omitted, they will be replaced in the output string
by a series of stars of the appropriate length.
Parameters: |
- year – The year element of the date/time
- month – The month element of the date/time
- day – The day element of the date/time
- hours – The hours element of the date/time
- minutes – The minutes element of the date/time
- seconds – The seconds element of the date/time
- microseconds – The microseconds element of the date/time
- timezone – The timeezone element of the date/time
|
Returns: | A WMI datetime string of the form: yyyymmddHHMMSS.mmmmmm+UUU
|
-
wmi.to_time(wmi_time)
Convenience wrapper to take a WMI datetime string of the form
yyyymmddHHMMSS.mmmmmm+UUU and return a 9-tuple containing the
individual elements, or None where string contains placeholder
stars.
Parameters: | wmi_time – The WMI datetime string in yyyymmddHHMMSS.mmmmmm+UUU format |
Returns: | A 9-tuple of (year, month, day, hours, minutes, seconds, microseconds, timezone) |
-
wmi._set(obj, attribute, value)
Helper function to add an attribute directly into the instance
dictionary, bypassing possible __getattr__ calls
Parameters: |
- obj – Any python object
- attribute – String containing attribute name
- value – Any python object
|
Implementation
These functions & classes are part of the underlying implementation and you
are not expected to call upon them explicitly. That said, it can be useful
to know what’s used and what you might use to assist in implementing some
functionality not currently exposed.
-
class wmi._wmi_method(ole_object, method_name)
A currying sort of wrapper around a WMI method name. It
abstract’s the method’s parameters and can be called like
a normal Python object passing in the parameter values.
Output parameters are returned from the call as a tuple.
In addition, the docstring is set up as the method’s
signature, including an indication as to whether any
given parameter is expecting an array, and what
special privileges are required to call the method.
-
__init__(ole_object, method_name)
Parameters: |
- ole_object – The WMI class/instance whose method is to be called
- method_name – The name of the method to be called
|
-
__call__(*args, **kwargs)
Execute the call to a WMI method, returning
a tuple (even if is of only one value) containing
the out and return parameters.
-
class wmi._wmi_object(ole_object, instance_of=None, fields=[], property_map={})
The heart of the WMI module: wraps the objects returned by COM
ISWbemObject interface and provide readier access to their properties
and methods resulting in a more Pythonic interface. Not usually
instantiated directly, rather as a result of calling a _wmi_class
on the parent _wmi_namespace.
If you get hold of a WMI-related COM object from some other
source than this module, you can wrap it in one of these objects
to get the benefits of the module:
import win32com.client
import wmi
wmiobj = win32com.client.GetObject ("winmgmts:Win32_LogicalDisk.DeviceID='C:'")
c_drive = wmi._wmi_object (wmiobj)
print c_drive
-
associators(wmi_association_class='', wmi_result_class='')
Return a list of objects related to this one, optionally limited
either by association class (ie the name of the class which relates
them) or by result class (ie the name of the class which would be
retrieved):
c = wmi.WMI ()
pp = c.Win32_ParallelPort ()[0]
for i in pp.associators (wmi_association_class="Win32_PortResource"):
print i
for i in pp.associators (wmi_result_class="Win32_PnPEntity"):
print i
-
derivation()
Return a tuple representing the object derivation for
this object, with the most specific object first:
pp0 = wmi.WMI ().Win32_ParallelPort ()[0]
print ' <- '.join (pp0.derivation ())
-
keys
A WMI object is uniquely defined by a set of properties
which constitute its keys. Lazily retrieves the keys for this
instance or class.
Returns: | list of key property names |
-
path()
Return the WMI URI to this object. Can be used to
determine the path relative to the parent namespace:
pp0 = wmi.WMI ().Win32_ParallelPort ()[0]
print pp0.path ().RelPath
-
put()
Push all outstanding property updates back to the
WMI database.
-
references(wmi_class='')
Return a list of associations involving this object, optionally
limited by the result class (the name of the association class).
NB Associations are treated specially; although WMI only returns
the string corresponding to the instance of each associated object,
this module will automatically convert that to the object itself:
c = wmi.WMI ()
sp = c.Win32_SerialPort ()[0]
for i in sp.references ():
print i
for i in sp.references (wmi_class="Win32_SerialPortSetting"):
print i
-
set(**kwargs)
Set several properties of the underlying object
at one go. This is particularly useful in combination
with the new () method below. However, an instance
which has been spawned in this way won’t have enough
information to write pack, so only try if the
instance has a path.
-
wmi_property(property_name)
Return the cached object representing one property
of this object
-
class wmi._wmi_class(namespace, wmi_class)
Currying class to assist in issuing queries against
a WMI namespace. The idea is that when someone issues
an otherwise unknown method against the WMI object, if
it matches a known WMI class a query object will be
returned which may then be called with one or more params
which will form the WHERE clause:
c = wmi.WMI ()
c_drives = c.Win32_LogicalDisk (Name='C:')
-
instances()
Return a list of instances of the WMI class
-
new(**kwargs)
This is the equivalent to the raw-WMI SpawnInstance_
method. Note that there are relatively few uses for
this, certainly fewer than you might imagine. Most
classes which need to create a new real instance
of themselves, eg Win32_Process, offer a .Create
method. SpawnInstance_ is generally reserved for
instances which are passed as parameters to such
.Create methods, a common example being the
Win32_SecurityDescriptor, passed to Win32_Share.Create
and other instances which need security.
The example here is Win32_ProcessStartup, which
controls the shown/hidden state etc. of a new
Win32_Process instance:
import win32con
import wmi
c = wmi.WMI ()
startup = c.Win32_ProcessStartup.new (ShowWindow=win32con.SW_SHOWMINIMIZED)
pid, retval = c.Win32_Process.Create (
CommandLine="notepad.exe",
ProcessStartupInformation=startup
)
Warning
previous versions of this docstring illustrated using this function
to create a new process. This is not a good example of its use;
it is better handled with something like the example above.
-
query(fields=[], **where_clause)
Make it slightly easier to query against the class,
by calling the namespace’s query with the class preset.
Won’t work if the class has been instantiated directly.
-
class wmi._wmi_namespace(namespace, find_classes)
A WMI root of a computer system. The classes attribute holds a list
of the classes on offer. This means you can explore a bit with
things like this:
c = wmi.WMI ()
for i in c.classes:
if "user" in i.lower ():
print i
-
fetch_as_classes(wmi_classname, fields=(), **where_clause)
Build and execute a wql query to fetch the specified list of fields from
the specified wmi_classname + where_clause, then return the results as
a list of simple class instances with attributes matching field_list.
If fields is left empty, select * and pre-load all class attributes for
each class returned.
-
fetch_as_lists(wmi_classname, fields, **where_clause)
Build and execute a wql query to fetch the specified list of fields from
the specified wmi_classname + where_clause, then return the results as
a list of lists whose values correspond to field_list.
-
handle()
The raw OLE object representing the WMI namespace
-
instances(class_name)
Return a list of instances of the WMI class. This is
(probably) equivalent to querying with no qualifiers:
wmi.WMI ().instances ("Win32_LogicalDisk")
# should be the same as
wmi.WMI ().Win32_LogicalDisk ()
-
new(wmi_class, **kwargs)
This is now implemented by a call to _wmi_class.new()
-
new_instance_of(wmi_class, **kwargs)
This is now implemented by a call to _wmi_class.new()
-
query(wql, instance_of=None, fields=[])
Perform an arbitrary query against a WMI object, and return
a list of _wmi_object representations of the results.
-
watch_for(raw_wql=None, notification_type='operation', wmi_class=None, delay_secs=1, fields=[], **where_clause)
Set up an event tracker on a WMI event. This function
returns an wmi_watcher which can be called to get the
next event:
c = wmi.WMI ()
raw_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process'"
watcher = c.watch_for (raw_wql=raw_wql)
while 1:
process_created = watcher ()
print process_created.Name
# or
watcher = c.watch_for (
notification_type="Creation",
wmi_class="Win32_Process",
delay_secs=2,
Name='calc.exe'
)
calc_created = watcher ()
Now supports timeout on the call to watcher:
import pythoncom
import wmi
c = wmi.WMI (privileges=["Security"])
watcher1 = c.watch_for (
notification_type="Creation",
wmi_class="Win32_NTLogEvent",
Type="error"
)
watcher2 = c.watch_for (
notification_type="Creation",
wmi_class="Win32_NTLogEvent",
Type="warning"
)
while 1:
try:
error_log = watcher1 (500)
except wmi.x_wmi_timed_out:
pythoncom.PumpWaitingMessages ()
else:
print error_log
try:
warning_log = watcher2 (500)
except wmi.x_wmi_timed_out:
pythoncom.PumpWaitingMessages ()
else:
print warning_log
Main Entry Points
-
wmi.WMI(computer='', impersonation_level='', authentication_level='', authority='', privileges='', moniker='', wmi=None, namespace='', suffix='', user='', password='', find_classes=False, debug=False)
The WMI constructor can either take a ready-made moniker or as many
parts of one as are necessary. Eg:
c = wmi.WMI (moniker="winmgmts:{impersonationLevel=Delegate}//remote")
# or
c = wmi.WMI (computer="remote", privileges=["!RemoteShutdown", "Security"])
I daren’t link to a Microsoft URL; they change so often. Try Googling for
WMI construct moniker and see what it comes back with.
For complete control, a named argument “wmi” can be supplied, which
should be a SWbemServices object, which you create yourself. Eg:
loc = win32com.client.Dispatch("WbemScripting.SWbemLocator")
svc = loc.ConnectServer(...)
c = wmi.WMI(wmi=svc)
This is the only way of connecting to a remote computer with a different
username, as the moniker syntax does not allow specification of a user
name.
If the wmi parameter is supplied, all other parameters are ignored.
-
wmi.connect_server(server, namespace='', user='', password='', locale='', authority='', impersonation_level='', authentication_level='', security_flags=128, named_value_set=None)
Return a remote server running WMI
Parameters: |
- server – name of the server
- namespace – namespace to connect to - defaults to whatever’s defined as default
- user – username to connect as, either local or domain (domname or user@domain for XP)
- password – leave blank to use current context
- locale – desired locale in form MS_XXXX (eg MS_409 for Am En)
- authority – either “Kerberos:” or an NT domain. Not needed if included in user
- impersonation_level – valid WMI impersonation level
- security_flags – if 0, connect will wait forever; if 0x80, connect will timeout at 2 mins
- named_value_set – typically empty, otherwise a context-specific SWbemNamedValueSet
|
Example:
remote_connetion = wmi.connect_server (
server="remote_machine", user="myname", password="mypassword"
)
c = wmi.WMI (wmi=remote_connection)
-
wmi.Registry(computer=None, impersonation_level='Impersonate', authentication_level='Default', authority=None, privileges=None, moniker=None)