1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123 try:
124 True, False
125 except NameError:
126 True = 1
127 False = 0
128
129 try:
130 object
131 except NameError:
133
134 __VERSION__ = "1.3.2"
135
136 _DEBUG = False
137
138 import sys
139 import re
140 import datetime
141 from win32com.client import GetObject, Dispatch
142 import pywintypes
143
145 """
146 A class which, when called on a win32com.client.Dispatch object,
147 provides lazy access to constants defined in the typelib.
148
149 They can be accessed as attributes of the _constants property.
150 From Thomas Heller on c.l.py
151 """
153 "@param comobj A COM object whose typelib constants are to be exposed"
154 comobj.__dict__["_constants"] = self
155
156 self.__typecomp = \
157 comobj._oleobj_.GetTypeInfo().GetContainingTypeLib()[0].GetTypeComp()
158
160 if name.startswith("__") and name.endswith("__"):
161 raise AttributeError, name
162 result = self.__typecomp.Bind(name)
163
164
165 if not result[0]:
166 raise AttributeError, name
167 return result[1].value
168
169 obj = GetObject ("winmgmts:")
170 ProvideConstants (obj)
171
172 wbemErrInvalidQuery = obj._constants.wbemErrInvalidQuery
173 wbemErrTimedout = obj._constants.wbemErrTimedout
174 wbemFlagReturnImmediately = obj._constants.wbemFlagReturnImmediately
175 wbemFlagForwardOnly = obj._constants.wbemFlagForwardOnly
176
178 """Convenience wrapper for displaying all manner of COM errors.
179 Raises a x_wmi exception with more useful information attached
180
181 @param error_info The structure attached to a pywintypes.com_error
182 """
183 hresult_code, hresult_name, additional_info, parameter_in_error = error_info
184 exception_string = ["%s - %s" % (hex (hresult_code), hresult_name)]
185 if additional_info:
186 wcode, source_of_error, error_description, whlp_file, whlp_context, scode = additional_info
187 exception_string.append (" Error in: %s" % source_of_error)
188 exception_string.append (" %s - %s" % (hex (scode), (error_description or "").strip ()))
189 raise x_wmi, "\n".join (exception_string)
190
191 BASE = datetime.datetime (1601, 1, 1)
193 return BASE + datetime.timedelta (microseconds=int (ns100) / 10)
194
195 -def from_time (year=None, month=None, day=None, hours=None, minutes=None, seconds=None, microseconds=None, timezone=None):
196 """
197 Convenience wrapper to take a series of date/time elements and return a WMI time
198 of the form yyyymmddHHMMSS.mmmmmm+UUU. All elements may be int, string or
199 omitted altogether. If omitted, they will be replaced in the output string
200 by a series of stars of the appropriate length.
201
202 @param year The year element of the date/time
203 @param month The month element of the date/time
204 @param day The day element of the date/time
205 @param hours The hours element of the date/time
206 @param minutes The minutes element of the date/time
207 @param seconds The seconds element of the date/time
208 @param microseconds The microseconds element of the date/time
209 @param timezone The timeezone element of the date/time
210
211 @return A WMI datetime string of the form: yyyymmddHHMMSS.mmmmmm+UUU
212 """
213 def str_or_stars (i, length):
214 if i is None:
215 return "*" * length
216 else:
217 return str (i).rjust (length, "0")
218
219 wmi_time = ""
220 wmi_time += str_or_stars (year, 4)
221 wmi_time += str_or_stars (month, 2)
222 wmi_time += str_or_stars (day, 2)
223 wmi_time += str_or_stars (hours, 2)
224 wmi_time += str_or_stars (minutes, 2)
225 wmi_time += str_or_stars (seconds, 2)
226 wmi_time += "."
227 wmi_time += str_or_stars (microseconds, 6)
228 wmi_time += str_or_stars (timezone, 4)
229
230 return wmi_time
231
233 """
234 Convenience wrapper to take a WMI datetime string of the form
235 yyyymmddHHMMSS.mmmmmm+UUU and return a 9-tuple containing the
236 individual elements, or None where string contains placeholder
237 stars.
238
239 @param wmi_time The WMI datetime string in yyyymmddHHMMSS.mmmmmm+UUU format
240
241 @return A 9-tuple of (year, month, day, hours, minutes, seconds, microseconds, timezone)
242 """
243 def int_or_none (s, start, end):
244 try:
245 return int (s[start:end])
246 except ValueError:
247 return None
248
249 year = int_or_none (wmi_time, 0, 4)
250 month = int_or_none (wmi_time, 4, 6)
251 day = int_or_none (wmi_time, 6, 8)
252 hours = int_or_none (wmi_time, 8, 10)
253 minutes = int_or_none (wmi_time, 10, 12)
254 seconds = int_or_none (wmi_time, 12, 14)
255 microseconds = int_or_none (wmi_time, 15, 21)
256 timezone = wmi_time[21:]
257
258 return year, month, day, hours, minutes, seconds, microseconds, timezone
259
260
261
262
265
268
271
274
275 WMI_EXCEPTIONS = {
276 wbemErrInvalidQuery : x_wmi_invalid_query,
277 wbemErrTimedout : x_wmi_timed_out
278 }
279
280 -def _set (obj, attribute, value):
281 """
282 Helper function to add an attribute directly into the instance
283 dictionary, bypassing possible __getattr__ calls
284
285 @param obj Any python object
286 @param attribute String containing attribute name
287 @param value Any python object
288 """
289 obj.__dict__[attribute] = value
290
292 """
293 A currying sort of wrapper around a WMI method name. It
294 abstract's the method's parameters and can be called like
295 a normal Python object passing in the parameter values.
296
297 Output parameters are returned from the call as a tuple.
298 In addition, the docstring is set up as the method's
299 signature, including an indication as to whether any
300 given parameter is expecting an array, and what
301 special privileges are required to call the method.
302 """
303
304 - def __init__ (self, ole_object, method_name):
305 """
306 @param ole_object The WMI class/instance whose method is to be called
307 @param method_name The name of the method to be called
308 """
309 try:
310 self.ole_object = Dispatch (ole_object)
311 self.method = ole_object.Methods_ (method_name)
312 self.qualifiers = {}
313 for q in self.method.Qualifiers_:
314 self.qualifiers[q.Name] = q.Value
315 self.provenance = "\n".join (self.qualifiers.get ("MappingStrings", []))
316
317 self.in_parameters = self.method.InParameters
318 self.out_parameters = self.method.OutParameters
319 if self.in_parameters is None:
320 self.in_parameter_names = []
321 else:
322 self.in_parameter_names = [(i.Name, i.IsArray) for i in self.in_parameters.Properties_]
323 if self.out_parameters is None:
324 self.out_parameter_names = []
325 else:
326 self.out_parameter_names = [(i.Name, i.IsArray) for i in self.out_parameters.Properties_]
327
328 doc = "%s (%s) => (%s)" % (
329 method_name,
330 ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.in_parameter_names]),
331 ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.out_parameter_names])
332 )
333 privileges = self.qualifiers.get ("Privileges", [])
334 if privileges:
335 doc += " | Needs: " + ", ".join (privileges)
336 self.__doc__ = doc
337 except pywintypes.com_error, error_info:
338 handle_com_error (error_info)
339
341 """
342 Execute the call to a WMI method, returning
343 a tuple (even if is of only one value) containing
344 the out and return parameters.
345 """
346 try:
347 if self.in_parameters:
348 parameter_names = {}
349 for name, is_array in self.in_parameter_names:
350 parameter_names[name] = is_array
351
352 parameters = self.in_parameters
353
354
355
356
357 for n_arg in range (len (args)):
358 arg = args[n_arg]
359 parameter = parameters.Properties_[n_arg]
360 if parameter.IsArray:
361 try: list (arg)
362 except TypeError: raise TypeError, "parameter %d must be iterable" % n_arg
363 parameter.Value = arg
364
365
366
367
368
369 for k, v in kwargs.items ():
370 is_array = parameter_names.get (k)
371 if is_array is None:
372 raise AttributeError, "%s is not a valid parameter for %s" % (k, self.__doc__)
373 else:
374 if is_array:
375 try: list (v)
376 except TypeError: raise TypeError, "%s must be iterable" % k
377 parameters.Properties_ (k).Value = v
378
379 result = self.ole_object.ExecMethod_ (self.method.Name, self.in_parameters)
380 else:
381 result = self.ole_object.ExecMethod_ (self.method.Name)
382
383 results = []
384 for name, is_array in self.out_parameter_names:
385 value = result.Properties_ (name).Value
386 if is_array:
387
388
389
390 results.append (list (value or []))
391 else:
392 results.append (value)
393 return tuple (results)
394
395 except pywintypes.com_error, error_info:
396 handle_com_error (error_info)
397
399 return "<function %s>" % self.__doc__
400
401
402
403
405 "A lightweight wrapper round an OLE WMI object"
406
407 - def __init__ (self, ole_object, instance_of=None, fields=[], property_map={}):
408 try:
409 _set (self, "ole_object", ole_object)
410 _set (self, "_instance_of", instance_of)
411 _set (self, "properties", {})
412 _set (self, "methods", {})
413 _set (self, "property_map", property_map)
414
415 if fields:
416 for field in fields:
417 self.properties[field] = None
418 else:
419 for p in ole_object.Properties_:
420 self.properties[p.Name] = None
421
422 for m in ole_object.Methods_:
423 self.methods[m.Name] = None
424
425 _set (self, "_properties", self.properties.keys ())
426 _set (self, "_methods", self.methods.keys ())
427
428 _set (self, "qualifiers", {})
429 for q in self.ole_object.Qualifiers_:
430 self.qualifiers[q.Name] = q.Value
431 _set (self, "is_association", self.qualifiers.has_key ("Association"))
432
433 except pywintypes.com_error, error_info:
434 handle_com_error (error_info)
435
437 """
438 For a call to print [object] return the OLE description
439 of the properties / values of the object
440 """
441 try:
442 return self.ole_object.GetObjectText_ ()
443 except pywintypes.com_error, error_info:
444 handle_com_error (error_info)
445
447 """
448 Indicate both the fact that this is a wrapped WMI object
449 and the WMI object's own identifying class.
450 """
451 try:
452 return "<%s: %s>" % (self.__class__.__name__, str (self.Path_.Path))
453 except pywintypes.com_error, error_info:
454 handle_com_error (error_info)
455
457 if self.properties[attribute] is None:
458 self.properties[attribute] = self.ole_object.Properties_ (attribute)
459 return self.properties[attribute]
460
462 if self.methods[attribute] is None:
463 self.methods[attribute] = _wmi_method (self.ole_object, attribute)
464 return self.methods[attribute]
465
467 """
468 Attempt to pass attribute calls to the proxied COM object.
469 If the attribute is recognised as a property, return its value;
470 if it is recognised as a method, return a method wrapper which
471 can then be called with parameters; otherwise pass the lookup
472 on to the underlying object.
473 """
474 try:
475 if self.properties.has_key (attribute):
476 factory = self.property_map.get (attribute, lambda x: x)
477 value = factory (self._cached_properties (attribute).Value)
478
479
480
481
482
483
484 if self.is_association:
485 return WMI (moniker=value)
486 else:
487 return value
488 elif self.methods.has_key (attribute):
489 return self._cached_methods (attribute)
490 else:
491 return getattr (self.ole_object, attribute)
492 except pywintypes.com_error, error_info:
493 handle_com_error (error_info)
494
496 """
497 If the attribute to be set is valid for the proxied
498 COM object, set that objects's parameter value; if not,
499 raise an exception.
500 """
501 try:
502 if self.properties.has_key (attribute):
503 self._cached_properties (attribute).Value = value
504 if self.ole_object.Path_.Path:
505 self.ole_object.Put_ ()
506 else:
507 raise AttributeError, attribute
508 except pywintypes.com_error, error_info:
509 handle_com_error (error_info)
510
512 """
513 Use WMI's CompareTo_ to compare this object with
514 another. Don't try to do anything if the other
515 object is not a wmi object. It might be possible
516 to compare this object's unique key with a string
517 or something, but this doesn't seem to be universal
518 enough to merit a special case.
519 """
520 if isinstance (other, self.__class__):
521 return self.ole_object.CompareTo_ (other.ole_object)
522 else:
523 raise x_wmi, "Can't compare a WMI object with something else"
524
526 """Return list of methods/properties for IPython completion"""
527 attribs = [str (x) for x in self.methods.keys ()]
528 attribs.extend ([str (x) for x in self.properties.keys ()])
529 return attribs
530
532 self.ole_object.Put_ ()
533
534 - def set (self, **kwargs):
535 """
536 Set several properties of the underlying object
537 at one go. This is particularly useful in combination
538 with the new () method below. However, an instance
539 which has been spawned in this way won't have enough
540 information to write pack, so only try if the
541 instance has a path.
542 """
543 if kwargs:
544 try:
545 for attribute, value in kwargs.items ():
546 if self.properties.has_key (attribute):
547 self._cached_properties (attribute).Value = value
548 else:
549 raise AttributeError, attribute
550
551
552
553
554 if self.ole_object.Path_.Path:
555 self.ole_object.Put_ ()
556 except pywintypes.com_error, error_info:
557 handle_com_error (error_info)
558
560 """
561 Return the WMI URI to this object. Can be used to
562 determine the path relative to the parent namespace. eg,
563
564 <pre class="code">
565 pp0 = wmi.WMI ().Win32_ParallelPort ()[0]
566 print pp0.path ().RelPath
567 </pre>
568 """
569 try:
570 return self.ole_object.Path_
571 except pywintypes.com_error, error_info:
572 handle_com_error (error_info)
573
575 """Return a tuple representing the object derivation for
576 this object, with the most specific object first. eg,
577
578 pp0 = wmi.WMI ().Win32_ParallelPort ()[0]
579 print ' <- '.join (pp0.derivation ())
580 """
581 try:
582 return self.ole_object.Derivation_
583 except pywintypes.com_error, error_info:
584 handle_com_error (error_info)
585
586 - def associators (self, wmi_association_class="", wmi_result_class=""):
587 """Return a list of objects related to this one, optionally limited
588 either by association class (ie the name of the class which relates
589 them) or by result class (ie the name of the class which would be
590 retrieved)
591
592 <pre class="code">
593 c = wmi.WMI ()
594 pp = c.Win32_ParallelPort ()[0]
595
596 for i in pp.associators (wmi_association_class="Win32_PortResource"):
597 print i
598
599 for i in pp.associators (wmi_result_class="Win32_PnPEntity"):
600 print i
601 </pre>
602 """
603 try:
604 return [
605 _wmi_object (i) for i in \
606 self.ole_object.Associators_ (
607 strAssocClass=wmi_association_class,
608 strResultClass=wmi_result_class
609 )
610 ]
611 except pywintypes.com_error, error_info:
612 handle_com_error (error_info)
613
615 """Return a list of associations involving this object, optionally
616 limited by the result class (the name of the association class).
617
618 NB Associations are treated specially; although WMI only returns
619 the string corresponding to the instance of each associated object,
620 this module will automatically convert that to the object itself.
621
622 <pre class="code">
623 c = wmi.WMI ()
624 sp = c.Win32_SerialPort ()[0]
625
626 for i in sp.references ():
627 print i
628
629 for i in sp.references (wmi_class="Win32_SerialPortSetting"):
630 print i
631 </pre>
632 """
633 try:
634 return [_wmi_object (i) for i in self.ole_object.References_ (strResultClass=wmi_class)]
635 except pywintypes.com_error, error_info:
636 handle_com_error (error_info)
637
638
639
640
642 """Slight extension of the _wmi_object class to allow
643 objects which are the result of events firing to return
644 extra information such as the type of event.
645 """
646 event_type_re = re.compile ("__Instance(Creation|Modification|Deletion)Event")
647 - def __init__ (self, event, event_info):
648 _wmi_object.__init__ (self, event)
649 _set (self, "event_type", None)
650 _set (self, "timestamp", None)
651 _set (self, "previous", None)
652
653 if event_info:
654 event_type = self.event_type_re.match (event_info.Path_.Class).group (1).lower ()
655 _set (self, "event_type", event_type)
656 if hasattr (event_info, "TIME_CREATED"):
657 _set (self, "timestamp", from_1601 (event_info.TIME_CREATED))
658 if hasattr (event_info, "PreviousInstance"):
659 _set (self, "previous", event_info.PreviousInstance)
660
661
662
663
665 """Currying class to assist in issuing queries against
666 a WMI namespace. The idea is that when someone issues
667 an otherwise unknown method against the WMI object, if
668 it matches a known WMI class a query object will be
669 returned which may then be called with one or more params
670 which will form the WHERE clause. eg,
671
672 <pre class="code">
673 c = wmi.WMI ()
674 c_drive = c.Win32_LogicalDisk (Name='C:')
675 </pre>
676 """
677 - def __init__ (self, namespace, wmi_class):
678 _wmi_object.__init__ (self, wmi_class)
679 _set (self, "_class_name", wmi_class.Path_.Class)
680 if namespace:
681 _set (self, "_namespace", namespace)
682 else:
683 class_moniker = wmi_class.Path_.DisplayName
684 winmgmts, namespace_moniker, class_name = class_moniker.split (":")
685 namespace = _wmi_namespace (GetObject (winmgmts + ":" + namespace_moniker), False)
686 _set (self, "_namespace", namespace)
687
688 - def query (self, fields=[], **where_clause):
689 """Make it slightly easier to query against the class,
690 by calling the namespace's query with the class preset.
691 Won't work if the class has been instantiated directly.
692 """
693 if self._namespace is None:
694 raise x_wmi_no_namespace, "You cannot query directly from a WMI class"
695
696 try:
697 field_list = ", ".join (fields) or "*"
698 wql = "SELECT " + field_list + " FROM " + self._class_name
699 if where_clause:
700 wql += " WHERE " + " AND ". join (["%s = '%s'" % (k, v) for k, v in where_clause.items ()])
701 return self._namespace.query (wql, self, fields)
702 except pywintypes.com_error, error_info:
703 handle_com_error (error_info)
704
705 __call__ = query
706
707 - def watch_for (
708 self,
709 notification_type="operation",
710 delay_secs=1,
711 **where_clause
712 ):
713 if self._namespace is None:
714 raise x_wmi_no_namespace, "You cannot watch directly from a WMI class"
715
716 return self._namespace.watch_for (
717 notification_type=notification_type,
718 wmi_class=self,
719 delay_secs=delay_secs,
720 **where_clause
721 )
722
724 """Return a list of instances of the WMI class
725 """
726 try:
727 return [_wmi_object (instance, self) for instance in self.Instances_ ()]
728 except pywintypes.com_error, error_info:
729 handle_com_error (error_info)
730
731 - def new (self, **kwargs):
732 """This is the equivalent to the raw-WMI SpawnInstance_
733 method. Note that there are relatively few uses for
734 this, certainly fewer than you might imagine. Most
735 classes which need to create a new *real* instance
736 of themselves, eg Win32_Process, offer a .Create
737 method. SpawnInstance_ is generally reserved for
738 instances which are passed as parameters to such
739 .Create methods, a common example being the
740 Win32_SecurityDescriptor, passed to Win32_Share.Create
741 and other instances which need security.
742
743 The example here is Win32_ProcessStartup, which
744 controls the shown/hidden state etc. of a new
745 Win32_Process instance.
746
747 <pre class="code">
748 import win32con
749 import wmi
750 c = wmi.WMI ()
751 startup = c.Win32_ProcessStartup.new (ShowWindow=win32con.SW_SHOWMINIMIZED)
752 pid, retval = c.Win32_Process.Create (
753 CommandLine="notepad.exe",
754 ProcessStartupInformation=startup
755 )
756 </pre>
757
758 NB previous versions of this module, used this function
759 to create new process. This is *not* a good example
760 of its use; it is better handled with something like
761 the example above.
762 """
763 try:
764 obj = _wmi_object (self.SpawnInstance_ (), self)
765 obj.set (**kwargs)
766 return obj
767 except pywintypes.com_error, error_info:
768 handle_com_error (error_info)
769
770
771
772
774 """Simple, data only result for targeted WMI queries which request
775 data only result classes via fetch_as_classes.
776 """
778 if attributes:
779 for attr in attributes:
780 self.__dict__[attr] = obj.Properties_ (attr).Value
781 else:
782 for p in obj.Properties_:
783 attr = p.Name
784 self.__dict__[attr] = obj.Properties_(attr).Value
785
786
787
788
790 """A WMI root of a computer system. The classes attribute holds a list
791 of the classes on offer. This means you can explore a bit with
792 things like this:
793
794 <pre class="code">
795 c = wmi.WMI ()
796 for i in c.classes:
797 if "user" in i.lower ():
798 print i
799 </pre>
800 """
801 - def __init__ (self, namespace, find_classes):
802 _set (self, "_namespace", namespace)
803
804
805
806 _set (self, "wmi", namespace)
807
808
809
810 self.classes = {}
811
812
813
814
815
816
817
818
819 if find_classes:
820 try:
821 self.classes.update (self.subclasses_of ())
822 except AttributeError:
823 pass
824
826 return "<_wmi_namespace: %s>" % self.wmi
827
830
831 - def get (self, moniker):
836
838 """The raw OLE object representing the WMI namespace"""
839 return self._namespace
840
842 classes = {}
843 for c in self._namespace.SubclassesOf (root):
844 klass = c.Path_.Class
845 if re.match (regex, klass):
846 classes[klass] = None
847 return classes
848
850 """Return a list of instances of the WMI class. This is
851 (probably) equivalent to querying with no qualifiers.
852
853 <pre class="code">
854 system.instances ("Win32_LogicalDisk")
855 # should be the same as
856 system.Win32_LogicalDisk ()
857 </pre>
858 """
859 try:
860 return [_wmi_object (obj) for obj in self._namespace.InstancesOf (class_name)]
861 except pywintypes.com_error, error_info:
862 handle_com_error (error_info)
863
864 - def new (self, wmi_class, **kwargs):
865 """This is now implemented by a call to _wmi_namespace.new (qv)"""
866 return getattr (self, wmi_class).new (**kwargs)
867
868 new_instance_of = new
869
871 """Execute a WQL query and return its raw results. Use the flags
872 recommended by Microsoft to achieve a read-only, semi-synchronous
873 query where the time is taken while looping through. Should really
874 be a generator, but ...
875 NB Backslashes need to be doubled up.
876 """
877 flags = wbemFlagReturnImmediately | wbemFlagForwardOnly
878 wql = wql.replace ("\\", "\\\\")
879 if _DEBUG: print "_raw_query(wql):", wql
880 try:
881 return self._namespace.ExecQuery (strQuery=wql, iFlags=flags)
882 except pywintypes.com_error, (hresult, hresult_text, additional, param_in_error):
883 raise WMI_EXCEPTIONS.get (hresult, x_wmi (hresult))
884
885 - def query (self, wql, instance_of=None, fields=[]):
886 """Perform an arbitrary query against a WMI object, and return
887 a list of _wmi_object representations of the results.
888 """
889 return [ _wmi_object (obj, instance_of, fields) for obj in self._raw_query(wql) ]
890
892 """Build and execute a wql query to fetch the specified list of fields from
893 the specified wmi_classname + where_clause, then return the results as
894 a list of simple class instances with attributes matching fields_list.
895
896 If fields is left empty, select * and pre-load all class attributes for
897 each class returned.
898 """
899 wql = "SELECT %s FROM %s" % (fields and ", ".join (fields) or "*", wmi_classname)
900 if where_clause:
901 wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()])
902 return [_wmi_result (obj, fields) for obj in self._raw_query(wql)]
903
905 """Build and execute a wql query to fetch the specified list of fields from
906 the specified wmi_classname + where_clause, then return the results as
907 a list of lists whose values correspond fields_list.
908 """
909 wql = "SELECT %s FROM %s" % (", ".join (fields), wmi_classname)
910 if where_clause:
911 wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()])
912 results = []
913 for obj in self._raw_query(wql):
914 results.append ([obj.Properties_ (field).Value for field in fields])
915 return results
916
917 - def watch_for (
918 self,
919 raw_wql=None,
920 notification_type="operation",
921 wmi_class=None,
922 delay_secs=1,
923 **where_clause
924 ):
925 """Set up an event tracker on a WMI event. This function
926 returns an wmi_watcher which can be called to get the
927 next event. eg,
928
929 <pre class="code">
930 c = wmi.WMI ()
931
932 raw_wql = "SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process'"
933 watcher = c.watch_for (raw_wql=raw_wql)
934 while 1:
935 process_created = watcher ()
936 print process_created.Name
937
938 # or
939
940 watcher = c.watch_for (
941 notification_type="Creation",
942 wmi_class="Win32_Process",
943 delay_secs=2,
944 Name='calc.exe'
945 )
946 calc_created = watcher ()
947 </pre>
948
949 Now supports timeout on the call to watcher, eg:
950
951 <pre class="code">
952 import pythoncom
953 import wmi
954 c = wmi.WMI (privileges=["Security"])
955 watcher1 = c.watch_for (
956 notification_type="Creation",
957 wmi_class="Win32_NTLogEvent",
958 Type="error"
959 )
960 watcher2 = c.watch_for (
961 notification_type="Creation",
962 wmi_class="Win32_NTLogEvent",
963 Type="warning"
964 )
965
966 while 1:
967 try:
968 error_log = watcher1 (500)
969 except wmi.x_wmi_timed_out:
970 pythoncom.PumpWaitingMessages ()
971 else:
972 print error_log
973
974 try:
975 warning_log = watcher2 (500)
976 except wmi.x_wmi_timed_out:
977 pythoncom.PumpWaitingMessages ()
978 else:
979 print warning_log
980 </pre>
981 """
982 if isinstance (wmi_class, _wmi_class):
983 class_name = wmi_class._class_name
984 else:
985 class_name = wmi_class
986 wmi_class = getattr (self, class_name)
987 is_extrinsic = "__ExtrinsicEvent" in wmi_class.derivation ()
988 if raw_wql:
989 wql = raw_wql
990 else:
991 if is_extrinsic:
992 if where_clause:
993 where = " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items ()])
994 else:
995 where = ""
996 wql = "SELECT * FROM " + class_name + where
997 else:
998 if where_clause:
999 where = " AND " + " AND ".join (["TargetInstance.%s = '%s'" % (k, v) for k, v in where_clause.items ()])
1000 else:
1001 where = ""
1002 wql = \
1003 "SELECT * FROM __Instance%sEvent WITHIN %d WHERE TargetInstance ISA '%s' %s" % \
1004 (notification_type, delay_secs, class_name, where)
1005
1006 if _DEBUG: print wql
1007
1008 try:
1009 return _wmi_watcher (self._namespace.ExecNotificationQuery (wql), is_extrinsic=is_extrinsic)
1010 except pywintypes.com_error, error_info:
1011 handle_com_error (error_info)
1012
1014 """Offer WMI classes as simple attributes. Pass through any untrapped
1015 unattribute to the underlying OLE object. This means that new or
1016 unmapped functionality is still available to the module user.
1017 """
1018
1019
1020
1021
1022
1023 try:
1024 return self._cached_classes (attribute)
1025 except pywintypes.com_error, error_info:
1026 try:
1027 return self._cached_classes ("Win32_" + attribute)
1028 except pywintypes.com_error, error_info:
1029 return getattr (self._namespace, attribute)
1030
1032 """Standard caching helper which keeps track of classes
1033 already retrieved by name and returns the existing object
1034 if found. If this is the first retrieval, store it and
1035 pass it back
1036 """
1037 if self.classes.get (class_name) is None:
1038 self.classes[class_name] = _wmi_class (self, self._namespace.Get (class_name))
1039 return self.classes[class_name]
1040
1042 """Return list of classes for IPython completion engine"""
1043 classes = [str (x) for x in self.classes.keys () if not x.startswith ('__')]
1044 return classes
1045
1046
1047
1048
1050 """Helper class for WMI.watch_for below (qv)"""
1051
1052 _event_property_map = {
1053 "TargetInstance" : _wmi_object,
1054 "PreviousInstance" : _wmi_object
1055 }
1056 - def __init__ (self, wmi_event, is_extrinsic):
1057 self.wmi_event = wmi_event
1058 self.is_extrinsic = is_extrinsic
1059
1061 """When called, return the instance which caused the event. Supports
1062 timeout in milliseconds (defaulting to infinite). If the watcher
1063 times out, x_wmi_timed_out is raised. This makes it easy to support
1064 watching for multiple objects.
1065 """
1066 try:
1067 event = self.wmi_event.NextEvent (timeout_ms)
1068 if self.is_extrinsic:
1069 return _wmi_event (event, None)
1070 else:
1071 return _wmi_event (
1072 event.Properties_ ("TargetInstance").Value,
1073 _wmi_object (event, property_map=self._event_property_map)
1074 )
1075 except pywintypes.com_error, error_info:
1076 hresult_code, hresult_name, additional_info, parameter_in_error = error_info
1077 if additional_info:
1078 wcode, source_of_error, error_description, whlp_file, whlp_context, scode = additional_info
1079 if scode == wbemErrTimedout:
1080 raise x_wmi_timed_out
1081 handle_com_error (error_info)
1082
1083 PROTOCOL = "winmgmts:"
1084 IMPERSONATION_LEVEL = "impersonate"
1085 AUTHENTICATION_LEVEL = "default"
1086 NAMESPACE = "root/cimv2"
1087 -def connect (
1088 computer=".",
1089 impersonation_level="",
1090 authentication_level="",
1091 authority="",
1092 privileges="",
1093 moniker="",
1094 wmi=None,
1095 namespace="",
1096 suffix="",
1097 user="",
1098 password="",
1099 find_classes=True,
1100 debug=False
1101 ):
1102 """The WMI constructor can either take a ready-made moniker or as many
1103 parts of one as are necessary. Eg,
1104
1105 <pre class="code">
1106 c = wmi.WMI (moniker="winmgmts:{impersonationLevel=Delegate}//remote")
1107
1108 # or
1109
1110 c = wmi.WMI (computer="remote", privileges=["!RemoteShutdown", "Security"])
1111 </pre>
1112
1113 I daren't link to a Microsoft URL; they change so often. Try Googling for
1114 WMI construct moniker and see what it comes back with.
1115
1116 For complete control, a named argument "wmi" can be supplied, which
1117 should be a SWbemServices object, which you create yourself. Eg,
1118
1119 <pre class="code">
1120 loc = win32com.client.Dispatch("WbemScripting.SWbemLocator")
1121 svc = loc.ConnectServer(...)
1122 c = wmi.WMI(wmi=svc)
1123 </pre>
1124
1125 This is the only way of connecting to a remote computer with a different
1126 username, as the moniker syntax does not allow specification of a user
1127 name.
1128
1129 If the "wmi" parameter is supplied, all other parameters are ignored.
1130 """
1131 global _DEBUG
1132 _DEBUG = debug
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142 try:
1143 if wmi:
1144 obj = wmi
1145
1146 elif moniker:
1147 if not moniker.startswith (PROTOCOL):
1148 moniker = PROTOCOL + moniker
1149 if _DEBUG: print moniker
1150 obj = GetObject (moniker)
1151
1152 else:
1153 if user:
1154 if impersonation_level or authentication_level or privileges or suffix:
1155 raise x_wmi, "You can't specify an impersonation, authentication or privilege as well as a username"
1156 else:
1157 obj = connect_server (
1158 server=computer,
1159 namespace=namespace,
1160 user=user,
1161 password=password,
1162 authority=authority
1163 )
1164
1165 else:
1166 moniker = construct_moniker (
1167 computer=computer,
1168 impersonation_level=impersonation_level or IMPERSONATION_LEVEL,
1169 authentication_level=authentication_level or AUTHENTICATION_LEVEL,
1170 authority=authority,
1171 privileges=privileges,
1172 namespace=namespace,
1173 suffix=suffix
1174 )
1175 if _DEBUG: print moniker
1176 obj = GetObject (moniker)
1177
1178 wmi_type = get_wmi_type (obj)
1179
1180 if wmi_type == "namespace":
1181 return _wmi_namespace (obj, find_classes)
1182 elif wmi_type == "class":
1183 return _wmi_class (None, obj)
1184 elif wmi_type == "instance":
1185 return _wmi_object (obj)
1186 else:
1187 raise x_wmi, "Unknown moniker type"
1188
1189 except pywintypes.com_error, error_info:
1190 handle_com_error (error_info)
1191
1192 WMI = connect
1193
1194 -def construct_moniker (
1195 computer=None,
1196 impersonation_level="Impersonate",
1197 authentication_level="Default",
1198 authority=None,
1199 privileges=None,
1200 namespace=None,
1201 suffix=None
1202 ):
1203 security = []
1204 if impersonation_level: security.append ("impersonationLevel=%s" % impersonation_level)
1205 if authentication_level: security.append ("authenticationLevel=%s" % authentication_level)
1206
1207
1208
1209 if authority and computer: security.append ("authority=%s" % authority)
1210 if privileges: security.append ("(%s)" % ", ".join (privileges))
1211
1212 moniker = [PROTOCOL]
1213 if security: moniker.append ("{%s}/" % ",".join (security))
1214 if computer: moniker.append ("/%s/" % computer)
1215 if namespace:
1216 parts = re.split (r"[/\\]", namespace)
1217 if parts[0] != 'root':
1218 parts.insert (0, "root")
1219 moniker.append ("/".join (parts))
1220 if suffix: moniker.append (":%s" % suffix)
1221 return "".join (moniker)
1222
1224 try:
1225 path = obj.Path_
1226 except AttributeError:
1227 return "namespace"
1228 else:
1229 if path.IsClass:
1230 return "class"
1231 else:
1232 return "instance"
1233
1234 -def connect_server (
1235 server,
1236 namespace = "",
1237 user = "",
1238 password = "",
1239 locale = "",
1240 authority = "",
1241 security_flags = 0,
1242 named_value_set = None
1243 ):
1244 """Return a remote server running WMI
1245
1246 server - name of the server
1247 namespace - namespace to connect to: defaults to whatever's defined as default
1248 user - username to connect as, either local or domain (dom\name or user@domain for XP)
1249 password: leave blank to use current context
1250 locale: desired locale in form MS_XXXX (eg MS_409 for Am En)
1251 authority: either "Kerberos:" or an NT domain. Not needed if included in user
1252 security_flags: if 0, connect will wait forever; if 0x80, connect will timeout at 2 mins
1253 named_value_set: typically empty, otherwise a context-specific SWbemNamedValueSet
1254
1255 <pre class="code">
1256 c = wmi.WMI (wmi=wmi.connect_server (server="remote_machine", user="myname", password="mypassword"))
1257 </pre>
1258 """
1259 if _DEBUG:
1260 print server
1261 print namespace
1262 print user
1263 print password
1264 print locale
1265 print authority
1266 print security_flags
1267 print named_value_set
1268
1269 return Dispatch ("WbemScripting.SWbemLocator").\
1270 ConnectServer (
1271 server,
1272 namespace,
1273 user,
1274 password,
1275 locale,
1276 authority,
1277 security_flags,
1278 named_value_set
1279 )
1280
1281 -def Registry (
1282 computer=None,
1283 impersonation_level="Impersonate",
1284 authentication_level="Default",
1285 authority=None,
1286 privileges=None,
1287 moniker=None
1288 ):
1289
1290 if not moniker:
1291 moniker = construct_moniker (
1292 computer=computer,
1293 impersonation_level=impersonation_level,
1294 authentication_level=authentication_level,
1295 authority=authority,
1296 privileges=privileges,
1297 namespace="default",
1298 suffix="StdRegProv"
1299 )
1300
1301 try:
1302 return _wmi_object (GetObject (moniker))
1303
1304 except pywintypes.com_error, error_info:
1305 handle_com_error (error_info)
1306
1307
1308
1309
1310 -def machines_in_domain (domain_name):
1311 adsi = Dispatch ("ADsNameSpaces")
1312 nt = adsi.GetObject ("","WinNT:")
1313 result = nt.OpenDSObject ("WinNT://%s" % domain_name, "", "", 0)
1314 result.Filter = ["computer"]
1315 domain = []
1316 for machine in result:
1317 domain.append (machine.Name)
1318 return domain
1319
1320
1321
1322
1323 if __name__ == '__main__':
1324 system = WMI ()
1325 for my_computer in system.Win32_ComputerSystem ():
1326 print "Disks on", my_computer.Name
1327 for disk in system.Win32_LogicalDisk ():
1328 print disk.Caption, disk.Description, disk.ProviderName or ""
1329