diff options
-rw-r--r-- | HISTORY | 186 | ||||
-rw-r--r-- | LICENSE | 54 | ||||
-rw-r--r-- | MANIFEST.in | 2 | ||||
-rw-r--r-- | README | 246 | ||||
-rwxr-xr-x | docs/class_diagram.png | bin | 20780 -> 20778 bytes | |||
-rw-r--r-- | docs/documentation.html | 282 | ||||
-rw-r--r-- | docs/index.html | 52 | ||||
-rw-r--r-- | docs/milestones.lnk.html | 24 | ||||
-rw-r--r-- | psutil/arch/mswindows/process_handles.c | 590 | ||||
-rw-r--r-- | psutil/arch/mswindows/process_handles.h | 8 | ||||
-rw-r--r-- | psutil/wmi.py | 2836 | ||||
-rw-r--r-- | test/_bsd.py | 282 | ||||
-rw-r--r-- | test/_linux.py | 48 | ||||
-rw-r--r-- | test/_osx.py | 128 | ||||
-rwxr-xr-x | test/_posix.py | 272 | ||||
-rw-r--r-- | test/_windows.py | 288 | ||||
-rw-r--r-- | test/test_psutil.py | 8 |
17 files changed, 2653 insertions, 2653 deletions
@@ -1,93 +1,93 @@ -Bug tracker at http://code.google.com/p/psutil/issues
-
-0.1.4 - XXXX-XX-XX
-------------------
-NEW FEATURES
- * Issue 91: per-process send_signal() and terminate() methods.
- * Issue 95: NoSuchProcess and AccessDenied exception classes now provide a
- "pid" and a "msg" attribute.
-
-BUGFIXES
- * Issue 94: suspend() raises OSError instead of AccessDenied.
-
-
-0.1.3 - 2010-03-02
-------------------
-NEW FEATURES
- * Issue 14: per-process username
- * Issue 51: per-process current working directory (Windows and Linux only)
- * Issue 59: Process.is_running() is now 10 times faster
- * Issue 61: added supoprt for FreeBSD 64 bit
- * Issue 71: implemented suspend/resume process
- * Issue 75: python 3 support
-
-BUGFIXES
- * Issue 36: process cpu_times() and memory_info() functions succeeded also for
- dead processes while a NoSuchProcess exception is supposed to be raised.
- * Issue 48: incorrect size for mib array defined in getcmdargs for BSD
- * Issue 49: possible memory leak due to missing free() on error condition on
- * Issue 50: fixed getcmdargs() memory fragmentation on BSD
- * Issue 55: test_pid_4 was failing on Windows Vista
- * Issue 57: some unit tests were failing on systems where no swap memory is
- available
- * Issue 58: is_running() is now called before kill() to make sure we are going
- to kill the correct process.
- * Issue 73: virtual memory size reported on OS X includes shared library size
- * Issue 77: NoSuchProcess wasn't raised on Process.create_time if kill() was
- used first.
-
-
-0.1.2 - 2009-05-06
-------------------
-NEW FEATURES
- * Issue 32: Per-process CPU user/kernel times
- * Issue 33: Process create time
- * Issue 34: Per-process CPU utilization percentage
- * Issue 38: Per-process memory usage (bytes)
- * Issue 41: Per-process memory utilization (percent)
- * Issue 39: System uptime
- * Issue 43: Total system virtual memory
- * Issue 46: Total system physical memory
- * Issue 44: Total system used/free virtual and physical memory
-
-BUGFIXES
- * Issue 36: NoSuchProcess not raised on Windows when accessing timing methods
- * Issue 40: test_get_cpu_times() failing on FreeBSD and OS X
- * Issue 42: get_memory_percent() raises AccessDenied on Windows
-
-
-0.1.1 - 2009-03-06
-------------------
-NEW FEATURES
- * Issue 4: FreeBSD support for all functions of psutil
- * Issue 9: Process.uid and Process.gid now retrieve process UID and GID.
- * Issue 11: Support for parent/ppid - Process.parent property returns a
- Process object representing the parent process, and Process.ppid returns
- the parent PID.
- * Issue 12 & 15: NoSuchProcess exception now raised when creating an object
- for a nonexistent process, or when retrieving information about a process
- that has gone away.
- * Issue 21: AccessDenied exception created for raising access denied errors
- from OSError or WindowsError on individual platforms.
- * Issue 26: psutil.process_iter() function to iterate over processes as
- Process objects with a generator.
- * Process objects can now also be compared with == operator for equality
- (PID, name, command line are compared).
-
-BUGFIXES
- * Issue 16: Special case for Windows' "System Idle Process" (PID 0) which
- otherwise would return an "invalid parameter" exception.
- * Issue 17: get_process_list() ignores NoSuchProcess and AccessDenied
- exceptions during building of the list.
- * Issue 22: Process(0).kill() was failing on Windows with an unset exception
- * Issue 23: Special case for pid_exists(0)
- * Issue 24: Process(0).kill() now raises AccessDenied exception instead of
- WindowsError.
- * Issue 30: psutil.get_pid_list() was returning two instances of PID 0 on OS
- X and FreeBSD platforms.
-
-
-0.1.0 - 2009-01-27
-------------------
-
- * Initial release.
+Bug tracker at http://code.google.com/p/psutil/issues + +0.1.4 - XXXX-XX-XX +------------------ +NEW FEATURES + * Issue 91: per-process send_signal() and terminate() methods. + * Issue 95: NoSuchProcess and AccessDenied exception classes now provide a + "pid" and a "msg" attribute. + +BUGFIXES + * Issue 94: suspend() raises OSError instead of AccessDenied. + + +0.1.3 - 2010-03-02 +------------------ +NEW FEATURES + * Issue 14: per-process username + * Issue 51: per-process current working directory (Windows and Linux only) + * Issue 59: Process.is_running() is now 10 times faster + * Issue 61: added supoprt for FreeBSD 64 bit + * Issue 71: implemented suspend/resume process + * Issue 75: python 3 support + +BUGFIXES + * Issue 36: process cpu_times() and memory_info() functions succeeded also for + dead processes while a NoSuchProcess exception is supposed to be raised. + * Issue 48: incorrect size for mib array defined in getcmdargs for BSD + * Issue 49: possible memory leak due to missing free() on error condition on + * Issue 50: fixed getcmdargs() memory fragmentation on BSD + * Issue 55: test_pid_4 was failing on Windows Vista + * Issue 57: some unit tests were failing on systems where no swap memory is + available + * Issue 58: is_running() is now called before kill() to make sure we are going + to kill the correct process. + * Issue 73: virtual memory size reported on OS X includes shared library size + * Issue 77: NoSuchProcess wasn't raised on Process.create_time if kill() was + used first. + + +0.1.2 - 2009-05-06 +------------------ +NEW FEATURES + * Issue 32: Per-process CPU user/kernel times + * Issue 33: Process create time + * Issue 34: Per-process CPU utilization percentage + * Issue 38: Per-process memory usage (bytes) + * Issue 41: Per-process memory utilization (percent) + * Issue 39: System uptime + * Issue 43: Total system virtual memory + * Issue 46: Total system physical memory + * Issue 44: Total system used/free virtual and physical memory + +BUGFIXES + * Issue 36: NoSuchProcess not raised on Windows when accessing timing methods + * Issue 40: test_get_cpu_times() failing on FreeBSD and OS X + * Issue 42: get_memory_percent() raises AccessDenied on Windows + + +0.1.1 - 2009-03-06 +------------------ +NEW FEATURES + * Issue 4: FreeBSD support for all functions of psutil + * Issue 9: Process.uid and Process.gid now retrieve process UID and GID. + * Issue 11: Support for parent/ppid - Process.parent property returns a + Process object representing the parent process, and Process.ppid returns + the parent PID. + * Issue 12 & 15: NoSuchProcess exception now raised when creating an object + for a nonexistent process, or when retrieving information about a process + that has gone away. + * Issue 21: AccessDenied exception created for raising access denied errors + from OSError or WindowsError on individual platforms. + * Issue 26: psutil.process_iter() function to iterate over processes as + Process objects with a generator. + * Process objects can now also be compared with == operator for equality + (PID, name, command line are compared). + +BUGFIXES + * Issue 16: Special case for Windows' "System Idle Process" (PID 0) which + otherwise would return an "invalid parameter" exception. + * Issue 17: get_process_list() ignores NoSuchProcess and AccessDenied + exceptions during building of the list. + * Issue 22: Process(0).kill() was failing on Windows with an unset exception + * Issue 23: Special case for pid_exists(0) + * Issue 24: Process(0).kill() now raises AccessDenied exception instead of + WindowsError. + * Issue 30: psutil.get_pid_list() was returning two instances of PID 0 on OS + X and FreeBSD platforms. + + +0.1.0 - 2009-01-27 +------------------ + + * Initial release. @@ -1,27 +1,27 @@ -psutil is distributed under BSD license reproduced below.
-
-Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola'
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of the psutil authors nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file +psutil is distributed under BSD license reproduced below. + +Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola' +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the psutil authors nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in index 513372bb..240e84d6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,4 +2,4 @@ include HISTORY LICENSE MANIFEST MANIFEST.in recursive-include docs * recursive-include psutil * recursive-include test * -global-exclude *.pyc *.pyo *.exe +global-exclude *.pyc *.pyo *.exe @@ -1,123 +1,123 @@ -
-Introduction
-============
-
-psutil is a module providing an interface for retrieving information on running
-processes in a portable way by using Python.
-It currently supports Linux, OS X, FreeBSD and Windows.
-
-psutil website is at http://code.google.com/p/psutil/
-
-The following document describes how to compile and install psutil from sources
-on different platforms.
-
-
-Using easy_install
-==================
-
-The easiest way to install psutil from sources is using easy_install.
-Get the latest easy_install version from http://pypi.python.org/pypi/setuptools
-and just run:
-
- > python easy_install psutil
-
-This should get the most updated psutil version from the Python pypi repository,
-unpack it, compile it and install it automatically.
-
-
-Installing on Windows using mingw32
-===================================
-
-After the mingw [1] environment is properly set up on your system you can
-compile Windows sources by entering:
-
- > setup.py build -c mingw32
-
-To compile and install just append the "install" keyword at the end of the
-command line above, like this:
-
- > setup.py build -c mingw32 install
-
-It might be possible that distutils will complain about missing gcc executable.
-That means you have to add mingw bin PATH variable first.
-Entering this line in the command prompt should do the work:
-
- > SET PATH=C:\MinGW\bin;%PATH%
-
-NOTE: this assumes MinGW is installed in C:\MinGW, if not simply replace the
-path in the command above with an appropriate location.
-
-[1] http://www.mingw.org/
-
-NOTE #2: as of right now all Windows functionnalities are written in pure C
-and no third party modules are required to be installed with the exception of
-the "username" functionnality which requires pywin32 extension to be installed
-separately.
-
-
-Installing on Windows using Visual Studio
-=========================================
-
-To use Visual Studio to install psutil, you must have the same version of
-Visual Studio used to compile your installation of Python. For older versions
-of Python that will be Visual Studio 2003. For 2.6 and later it should be
-Visual Studio 2008. If you do not have the requisite version of Visual Studio
-available then it is recommended to use MinGW to compile psutil instead.
-
-If you do have Visual Studio installed, you can use the basic distutils
-commands:
-
- > setup.py build
-
-or to install and build:
-
- > setup.py install
-
-distutils should take care of any necessary magic to compile from there.
-
-
-Installing on OS X
-==================
-
-OS X installation from source will require gcc which you can obtain as part of
-the 'XcodeTools' installer from Apple. Then you can run the standard distutils
-commands:
-
-to build only:
-
- > ./setup.py build
-
-to install and build:
-
- > ./setup.py install
-
-NOTE: due to developer's hardware limitations psutil has only been compiled and
-tested on OS X 10.4.11 so may or may not work on other versions.
-
-
-Installing on FreeBSD
-=====================
-
-The same compiler used to install Python must be present on the system in order
-to build modules using distutils. Assuming it is installed, you can build using
-the standard distutils commands:
-
-build only:
-
- > ./setup.py build
-
-install and build:
-
- > ./setup.py install
-
-
-Installing on Linux
-===================
-
-Standard distutils installation steps should apply here. At the current time
-the Linux port of psutil does not require any C modules, so can be installed
-without need for a compiler using disutils:
-
-install/build:
-
- > ./setup.py install
+ +Introduction +============ + +psutil is a module providing an interface for retrieving information on running +processes in a portable way by using Python. +It currently supports Linux, OS X, FreeBSD and Windows. + +psutil website is at http://code.google.com/p/psutil/ + +The following document describes how to compile and install psutil from sources +on different platforms. + + +Using easy_install +================== + +The easiest way to install psutil from sources is using easy_install. +Get the latest easy_install version from http://pypi.python.org/pypi/setuptools +and just run: + + > python easy_install psutil + +This should get the most updated psutil version from the Python pypi repository, +unpack it, compile it and install it automatically. + + +Installing on Windows using mingw32 +=================================== + +After the mingw [1] environment is properly set up on your system you can +compile Windows sources by entering: + + > setup.py build -c mingw32 + +To compile and install just append the "install" keyword at the end of the +command line above, like this: + + > setup.py build -c mingw32 install + +It might be possible that distutils will complain about missing gcc executable. +That means you have to add mingw bin PATH variable first. +Entering this line in the command prompt should do the work: + + > SET PATH=C:\MinGW\bin;%PATH% + +NOTE: this assumes MinGW is installed in C:\MinGW, if not simply replace the +path in the command above with an appropriate location. + +[1] http://www.mingw.org/ + +NOTE #2: as of right now all Windows functionnalities are written in pure C +and no third party modules are required to be installed with the exception of +the "username" functionnality which requires pywin32 extension to be installed +separately. + + +Installing on Windows using Visual Studio +========================================= + +To use Visual Studio to install psutil, you must have the same version of +Visual Studio used to compile your installation of Python. For older versions +of Python that will be Visual Studio 2003. For 2.6 and later it should be +Visual Studio 2008. If you do not have the requisite version of Visual Studio +available then it is recommended to use MinGW to compile psutil instead. + +If you do have Visual Studio installed, you can use the basic distutils +commands: + + > setup.py build + +or to install and build: + + > setup.py install + +distutils should take care of any necessary magic to compile from there. + + +Installing on OS X +================== + +OS X installation from source will require gcc which you can obtain as part of +the 'XcodeTools' installer from Apple. Then you can run the standard distutils +commands: + +to build only: + + > ./setup.py build + +to install and build: + + > ./setup.py install + +NOTE: due to developer's hardware limitations psutil has only been compiled and +tested on OS X 10.4.11 so may or may not work on other versions. + + +Installing on FreeBSD +===================== + +The same compiler used to install Python must be present on the system in order +to build modules using distutils. Assuming it is installed, you can build using +the standard distutils commands: + +build only: + + > ./setup.py build + +install and build: + + > ./setup.py install + + +Installing on Linux +=================== + +Standard distutils installation steps should apply here. At the current time +the Linux port of psutil does not require any C modules, so can be installed +without need for a compiler using disutils: + +install/build: + + > ./setup.py install diff --git a/docs/class_diagram.png b/docs/class_diagram.png Binary files differindex 7c64d3f2..2dc22a72 100755 --- a/docs/class_diagram.png +++ b/docs/class_diagram.png diff --git a/docs/documentation.html b/docs/documentation.html index e2c80b2a..f3d9d8d3 100644 --- a/docs/documentation.html +++ b/docs/documentation.html @@ -1,141 +1,141 @@ -<html><head>
-<meta http-equiv="content-type" content="text/html; charset=UTF-8">
-
-
-
-
-
- <title>psutil - Documentation</title>
- </head><body>
-
-
-
-
- <div id="wikicontent">
- <table border="0" cellpadding="0" cellspacing="0" width="100%">
- <tbody><tr>
-
- <td class="vt" id="wikimaincol" width="100%">
-
- <div id="wikiheader" style="margin-bottom: 1em;">
-
- <span style="font-size: 120%; font-weight: bold;">Documentation</span>
-
-
-
- <div style="font-style: italic; margin-top: 3px;">API reference</div>
-
- </div>
- <h1><a name="API_Reference">API Reference</a></h1><h2><a
-name="Exceptions">Exceptions</a></h2><p><a name="Exceptions">psutil.<strong>NoSuchProcess</strong></a><strong></strong><br>
- </p><blockquote>Raised when no process with the given PID/parameter was
- found in the current process list.
-</blockquote><p></p><p>psutil.<strong>AccessDenied</strong><br>
- </p><blockquote>Exception raised when permission to perform an action
-is denied.
-</blockquote><p></p><hr><h2><a name="Classes">Classes</a></h2><p><a
-name="Classes">psutil.<strong>Process(</strong><i>pid</i><strong>)</strong>
- </a></p><blockquote><a name="Classes">A class which represents an OS
-process.
-</a></blockquote><ul><li><a name="Classes"><strong>pid</strong><br>The
-process pid. </a></li></ul><ul><li><a name="Classes"><strong>ppid</strong><br>The
- process parent pid. </a></li></ul><ul><li><a name="Classes"><strong>parent</strong><br>Return
- the parent process as a <tt>Process</tt> object. If no ppid is known
-then return <tt>None</tt>. </a></li></ul><ul><li><a name="Classes"><strong>name</strong><br>The
- process name. </a></li></ul><ul><li><a name="Classes"><strong>path</strong><br>The
- process path. </a></li></ul><ul><li><a name="Classes"><strong>cmdline</strong><br>The
- command line process has been called with. </a></li></ul><ul><li><a
-name="Classes"><strong>create_time</strong><br> The process creation
-time as a floating point number expressed in seconds since the epoch, in
- UTC. </a></li></ul><ul><li><a name="Classes"><strong>uid</strong><br>The
- real user id of the current process. Where uid doesn't make sense (<i>Windows</i>)
- always return <tt>-1</tt>. </a></li></ul><ul><li><a name="Classes"><strong>gid</strong><br>The
- real group id of the current process. Where gid doesn't make sense (<i>Windows</i>)
- always return <tt>-1</tt>. </a></li></ul><ul><li><a name="Classes"><strong>username</strong><br>The
- name of the user that owns the process. </a></li></ul><blockquote><a
-name="Classes"><i>New in 0.1.3</i>
-</a></blockquote><ul><li><a name="Classes"><strong>getcwd()</strong><br>Return
- a string representing the process current working directory. </a></li></ul><blockquote><a
- name="Classes"><i>New in 0.1.3 - Availability <strong>Windows, Linux</strong></i>
-
-</a></blockquote><ul><li><a name="Classes"><strong>get_cpu_times()</strong><br>Return
- a tuple whose values are process CPU user and system times which means
-the amount of time expressed in seconds that a process has spent in
-user/system mode. </a></li></ul><ul><li><a name="Classes"><strong>get_cpu_percent()</strong><br>Compare
- process times to system time elapsed since last call and calculate CPU
-utilization as a percentage. It is recommended for accuracy that this
-function be called with at least 1 second between calls. The initial
-delta is calculated from the instantiation of the Process object. </a></li></ul><ul><li><a
- name="Classes"><strong>get_memory_info()</strong><br>Return a tuple
-representing RSS (Resident Set Size) and VMS (Virtual Memory Size) in
-bytes.<br>On UNIX RSS and VMS are the same values shown by ps. On
-Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns of
-taskmgr.exe. </a></li></ul><ul><li><a name="Classes"><strong>get_memory_percent()</strong><br>Compare
- physical system memory to process resident memory and calculate process
- memory utilization as a percentage. </a></li></ul><ul><li><a
-name="Classes"><strong>is_running()</strong><br>Return whether the
-current process is running in the current process list. </a></li></ul><ul><li><a
- name="Classes"><strong>suspend()</strong><br>Suspend process execution.
- </a></li></ul><blockquote><a name="Classes"><i>New in 0.1.3</i>
-</a></blockquote><ul><li><a name="Classes"><strong>resume()</strong><br>Resume
- process execution. </a></li></ul><blockquote><a name="Classes"><i>New
-in 0.1.3</i>
-</a></blockquote><ul><li><a name="Classes"><strong>kill([</strong><i><tt>sig</tt></i><strong>])</strong><br>Kill
- the current process by using signal <i>sig</i> (defaults to SIGKILL). </a></li></ul><hr><h2><a
- name="Functions">Functions</a></h2><p><a name="Functions">psutil.<strong>get_pid_list()</strong><br>
- </a></p><blockquote><a name="Functions">Return a list of current
-running PIDs.
-</a></blockquote><p></p><p><a name="Functions">psutil.<strong>pid_exists(</strong><i>pid</i><strong>)</strong><br>
- </a></p><blockquote><a name="Functions">Check whether the given PID
-exists in the current process list.
-</a></blockquote><p></p><p><a name="Functions">psutil.<strong>process_iter()</strong><br>
- </a></p><blockquote><a name="Functions">Return an iterator yielding a
-Process class instances for all running processes on the local machine.
-</a></blockquote><p></p><hr><h2><a name="System_related_objects">System
-related objects</a></h2><p><a name="System_related_objects">psutil.<strong>cpu_percent()</strong>
- </a></p><blockquote><a name="System_related_objects">Return the current
- system-wide CPU utilization as a percentage. For highest accuracy, it
-is recommended that this be called at least 1/10th of a second after
-importing the module or calling cpu_percent() in a previous call, to
-allow for a larger time delta from which to calculate the percentage
-value.
-</a></blockquote><p></p><p><a name="System_related_objects">psutil.<strong>cpu_times()</strong>
- </a></p><blockquote><a name="System_related_objects">Return system CPU
-times as a <tt>CPUTimes</tt> class object. Every CPU time is accessible
-in form of a <tt>CPUTimes</tt> attribute and represents the time CPU has
- spent in the given mode.<br>The attributes availability varies
-depending on the platform. Here follows a list of all available
-attributes:
-</a></blockquote><p></p><blockquote><a name="System_related_objects">- <strong>user</strong><br>
-
-- <strong>system</strong><br>
-- <strong>idle</strong><br>
-- <strong>nice</strong> <i>(UNIX)</i><br>
-- <strong>iowait</strong> <i>(Linux)</i><br>
-- <strong>irq</strong> <i>(Linux, FreeBSD)</i><br>
-- <strong>softirq</strong> <i>(Linux)</i><br>
-</a></blockquote><p><a name="System_related_objects">psutil.<strong>TOTAL_PHYMEM</strong><br>
- psutil.<strong>avail_phymem()</strong><br> psutil.<strong>used_phymem()</strong><br>
- </a></p><blockquote><a name="System_related_objects">Return the amount
-of total, available and used physical memory on the system, in bytes.
-</a></blockquote><p></p><p><a name="System_related_objects">psutil.<strong>total_virtmem()</strong><br>
- psutil.<strong>avail_virtmem()</strong><br> psutil.<strong>used_virtmem()</strong><br>
- </a></p><blockquote><a name="System_related_objects">Return the amount
-of total, available and used virtual memory on the system, in bytes.<br>On
- Linux they match the values returned by <tt>free</tt> command line
-utility. On OS X and FreeBSD they represent the same values as returned
-by <tt>sysctl vm.vmtotal</tt>. On Windows they are determined by reading
- the <tt>*PageFile</tt> values of </a><a
-href="http://msdn.microsoft.com/en-us/library/aa366770%28VS.85%29.aspx"
-rel="nofollow">MEMORYSTATUSEX</a> structure.
-</blockquote><p></p>
- </td>
- </tr>
- </tbody></table>
- </div>
-
-
-
-
-
- </body></html>
\ No newline at end of file +<html><head> +<meta http-equiv="content-type" content="text/html; charset=UTF-8"> + + + + + + <title>psutil - Documentation</title> + </head><body> + + + + + <div id="wikicontent"> + <table border="0" cellpadding="0" cellspacing="0" width="100%"> + <tbody><tr> + + <td class="vt" id="wikimaincol" width="100%"> + + <div id="wikiheader" style="margin-bottom: 1em;"> + + <span style="font-size: 120%; font-weight: bold;">Documentation</span> + + + + <div style="font-style: italic; margin-top: 3px;">API reference</div> + + </div> + <h1><a name="API_Reference">API Reference</a></h1><h2><a +name="Exceptions">Exceptions</a></h2><p><a name="Exceptions">psutil.<strong>NoSuchProcess</strong></a><strong></strong><br> + </p><blockquote>Raised when no process with the given PID/parameter was + found in the current process list. +</blockquote><p></p><p>psutil.<strong>AccessDenied</strong><br> + </p><blockquote>Exception raised when permission to perform an action +is denied. +</blockquote><p></p><hr><h2><a name="Classes">Classes</a></h2><p><a +name="Classes">psutil.<strong>Process(</strong><i>pid</i><strong>)</strong> + </a></p><blockquote><a name="Classes">A class which represents an OS +process. +</a></blockquote><ul><li><a name="Classes"><strong>pid</strong><br>The +process pid. </a></li></ul><ul><li><a name="Classes"><strong>ppid</strong><br>The + process parent pid. </a></li></ul><ul><li><a name="Classes"><strong>parent</strong><br>Return + the parent process as a <tt>Process</tt> object. If no ppid is known +then return <tt>None</tt>. </a></li></ul><ul><li><a name="Classes"><strong>name</strong><br>The + process name. </a></li></ul><ul><li><a name="Classes"><strong>path</strong><br>The + process path. </a></li></ul><ul><li><a name="Classes"><strong>cmdline</strong><br>The + command line process has been called with. </a></li></ul><ul><li><a +name="Classes"><strong>create_time</strong><br> The process creation +time as a floating point number expressed in seconds since the epoch, in + UTC. </a></li></ul><ul><li><a name="Classes"><strong>uid</strong><br>The + real user id of the current process. Where uid doesn't make sense (<i>Windows</i>) + always return <tt>-1</tt>. </a></li></ul><ul><li><a name="Classes"><strong>gid</strong><br>The + real group id of the current process. Where gid doesn't make sense (<i>Windows</i>) + always return <tt>-1</tt>. </a></li></ul><ul><li><a name="Classes"><strong>username</strong><br>The + name of the user that owns the process. </a></li></ul><blockquote><a +name="Classes"><i>New in 0.1.3</i> +</a></blockquote><ul><li><a name="Classes"><strong>getcwd()</strong><br>Return + a string representing the process current working directory. </a></li></ul><blockquote><a + name="Classes"><i>New in 0.1.3 - Availability <strong>Windows, Linux</strong></i> + +</a></blockquote><ul><li><a name="Classes"><strong>get_cpu_times()</strong><br>Return + a tuple whose values are process CPU user and system times which means +the amount of time expressed in seconds that a process has spent in +user/system mode. </a></li></ul><ul><li><a name="Classes"><strong>get_cpu_percent()</strong><br>Compare + process times to system time elapsed since last call and calculate CPU +utilization as a percentage. It is recommended for accuracy that this +function be called with at least 1 second between calls. The initial +delta is calculated from the instantiation of the Process object. </a></li></ul><ul><li><a + name="Classes"><strong>get_memory_info()</strong><br>Return a tuple +representing RSS (Resident Set Size) and VMS (Virtual Memory Size) in +bytes.<br>On UNIX RSS and VMS are the same values shown by ps. On +Windows RSS and VMS refer to "Mem Usage" and "VM Size" columns of +taskmgr.exe. </a></li></ul><ul><li><a name="Classes"><strong>get_memory_percent()</strong><br>Compare + physical system memory to process resident memory and calculate process + memory utilization as a percentage. </a></li></ul><ul><li><a +name="Classes"><strong>is_running()</strong><br>Return whether the +current process is running in the current process list. </a></li></ul><ul><li><a + name="Classes"><strong>suspend()</strong><br>Suspend process execution. + </a></li></ul><blockquote><a name="Classes"><i>New in 0.1.3</i> +</a></blockquote><ul><li><a name="Classes"><strong>resume()</strong><br>Resume + process execution. </a></li></ul><blockquote><a name="Classes"><i>New +in 0.1.3</i> +</a></blockquote><ul><li><a name="Classes"><strong>kill([</strong><i><tt>sig</tt></i><strong>])</strong><br>Kill + the current process by using signal <i>sig</i> (defaults to SIGKILL). </a></li></ul><hr><h2><a + name="Functions">Functions</a></h2><p><a name="Functions">psutil.<strong>get_pid_list()</strong><br> + </a></p><blockquote><a name="Functions">Return a list of current +running PIDs. +</a></blockquote><p></p><p><a name="Functions">psutil.<strong>pid_exists(</strong><i>pid</i><strong>)</strong><br> + </a></p><blockquote><a name="Functions">Check whether the given PID +exists in the current process list. +</a></blockquote><p></p><p><a name="Functions">psutil.<strong>process_iter()</strong><br> + </a></p><blockquote><a name="Functions">Return an iterator yielding a +Process class instances for all running processes on the local machine. +</a></blockquote><p></p><hr><h2><a name="System_related_objects">System +related objects</a></h2><p><a name="System_related_objects">psutil.<strong>cpu_percent()</strong> + </a></p><blockquote><a name="System_related_objects">Return the current + system-wide CPU utilization as a percentage. For highest accuracy, it +is recommended that this be called at least 1/10th of a second after +importing the module or calling cpu_percent() in a previous call, to +allow for a larger time delta from which to calculate the percentage +value. +</a></blockquote><p></p><p><a name="System_related_objects">psutil.<strong>cpu_times()</strong> + </a></p><blockquote><a name="System_related_objects">Return system CPU +times as a <tt>CPUTimes</tt> class object. Every CPU time is accessible +in form of a <tt>CPUTimes</tt> attribute and represents the time CPU has + spent in the given mode.<br>The attributes availability varies +depending on the platform. Here follows a list of all available +attributes: +</a></blockquote><p></p><blockquote><a name="System_related_objects">- <strong>user</strong><br> + +- <strong>system</strong><br> +- <strong>idle</strong><br> +- <strong>nice</strong> <i>(UNIX)</i><br> +- <strong>iowait</strong> <i>(Linux)</i><br> +- <strong>irq</strong> <i>(Linux, FreeBSD)</i><br> +- <strong>softirq</strong> <i>(Linux)</i><br> +</a></blockquote><p><a name="System_related_objects">psutil.<strong>TOTAL_PHYMEM</strong><br> + psutil.<strong>avail_phymem()</strong><br> psutil.<strong>used_phymem()</strong><br> + </a></p><blockquote><a name="System_related_objects">Return the amount +of total, available and used physical memory on the system, in bytes. +</a></blockquote><p></p><p><a name="System_related_objects">psutil.<strong>total_virtmem()</strong><br> + psutil.<strong>avail_virtmem()</strong><br> psutil.<strong>used_virtmem()</strong><br> + </a></p><blockquote><a name="System_related_objects">Return the amount +of total, available and used virtual memory on the system, in bytes.<br>On + Linux they match the values returned by <tt>free</tt> command line +utility. On OS X and FreeBSD they represent the same values as returned +by <tt>sysctl vm.vmtotal</tt>. On Windows they are determined by reading + the <tt>*PageFile</tt> values of </a><a +href="http://msdn.microsoft.com/en-us/library/aa366770%28VS.85%29.aspx" +rel="nofollow">MEMORYSTATUSEX</a> structure. +</blockquote><p></p> + </td> + </tr> + </tbody></table> + </div> + + + + + + </body></html> diff --git a/docs/index.html b/docs/index.html index 10a716e5..1742d9c9 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,26 +1,26 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<title>psutil - Home</title>
-</head>
-
-<body>
-<div id="wikicontent">
- <h1>Python process utilities (psutil)</h1>
- <h1><a name="Summary" id="Summary">Summary</a></h1>
- <p><a name="Summary" id="Summary">psutil is a module providing an interface for retrieving information on running processes and system utilization (CPU, memory) in a portable way by using Python. </a></p>
- <p><a name="Summary" id="Summary">It currently supports Linux, OS X, FreeBSD and Windows. </a></p>
- <h1><a name="Example_usage" id="Example_usage">Example usage</a></h1>
- <pre><a name="Example_usage" id="Example_usage">>>> import psutil<br />>>> psutil.get_pid_list()<br />[1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224,<br />268, 1215, 1216, 1220, 1221, 1243, 1244, 1301, 1601, 2237, 2355,<br />2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, <br />4263, 4282, 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, <br />4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, 5167, 5234, 5235, <br />5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071]<br />>>> p = psutil.Process(7055)<br />>>> p.name<br />'python'<br />>>> p.path<br />'/usr/bin'<br />>>> p.cmdline<br />['/usr/bin/python', '-O']<br />>>> p.uid<br />1000<br />>>> p.gid<br />1000<br />>>> rss, vms = p.get_memory_info()<br />>>> print "Resident memory: %s KB" %(rss / 1024)<br />Resident memory: 3768 KB<br />>>> print "Virtual memory: %s KB" %(vms / 1024)<br />Virtual memory: 6176 KB<br />>>> <br />>>> psutil.test()<br />UID PID %CPU %MEM VSZ RSS START TIME COMMAND<br />0 0 0.0 0.0 0 0 Mar20 00:00 [sched]<br />0 1 0.0 0.3 1740 600 Mar20 00:04 /sbin/init<br />0 2 0.0 0.0 0 0 Mar20 00:00 [kthreadd]<br />0 3 0.0 0.0 0 0 Mar20 00:00 [migration/0]<br />0 4 0.0 0.0 0 0 Mar20 00:05 [ksoftirqd/0]<br />0 5 0.0 0.0 0 0 Mar20 00:00 [watchdog/0]<br />0 6 0.0 0.0 0 0 Mar20 00:03 [events/0]<br />0 7 0.0 0.0 0 0 Mar20 00:00 [khelper]<br />0 46 0.0 0.0 0 0 Mar20 00:00 [kintegrityd/0]<br />0 48 0.0 0.0 0 0 Mar20 00:01 [kblockd/0]<br />0 50 0.0 0.0 0 0 Mar20 00:00 [kacpid]<br />0 51 0.0 0.0 0 0 Mar20 00:00 [kacpi_notify]<br />0 179 0.0 0.0 0 0 Mar20 00:00 [cqueue]<br />0 183 0.0 0.0 0 0 Mar20 00:00 [kseriod]<br />0 223 0.0 0.0 0 0 Mar20 00:00 [pdflush]<br />0 224 0.0 0.0 0 0 Mar20 00:04 [pdflush]<br />0 225 0.0 0.0 0 0 Mar20 00:01 [kswapd0]<br />0 269 0.0 0.0 0 0 Mar20 00:00 [aio/0]<br />0 1221 0.0 0.0 0 0 Mar20 00:00 [ksuspend_usbd]<br />0 1222 0.0 0.0 0 0 Mar20 00:00 [khubd]<br />0 1226 0.0 0.0 0 0 Mar20 00:00 [ata/0]<br />0 1227 0.0 0.0 0 0 Mar20 00:00 [ata_aux]<br />0 1245 0.0 0.0 0 0 Mar20 00:04 [mpt_poll_0]<br />0 1402 0.0 0.0 0 0 Mar20 00:00 [scsi_eh_0]<br />0 1843 0.0 0.0 0 0 Mar20 00:00 [scsi_eh_1]<br />0 1844 0.0 0.0 0 0 Mar20 00:00 [scsi_eh_2]<br />0 2241 0.0 0.0 0 0 Mar20 00:06 [kjournald]<br />0 2359 0.0 0.4 2312 740 Mar20 00:02 /sbin/udevd --daemon<br />0 2678 0.0 0.0 0 0 Mar20 00:00 [kgameportd]<br />0 2796 0.0 0.0 0 0 Mar20 00:00 [kpsmoused]<br />0 4209 0.0 0.3 1780 536 Mar20 00:00 /sbin/getty 38400 tty4<br />0 4210 0.0 0.3 1780 536 Mar20 00:00 /sbin/getty 38400 tty5<br />0 4215 0.0 0.3 1780 540 Mar20 00:00 /sbin/getty 38400 tty2<br />0 4216 0.0 0.3 1780 540 Mar20 00:00 /sbin/getty 38400 tty3<br />0 4217 0.0 0.3 1780 540 Mar20 00:00 /sbin/getty 38400 tty6<br />101 4258 0.0 0.4 2012 712 Mar20 00:01 /sbin/syslogd -u syslog<br />0 4276 0.0 0.4 1936 544 Mar20 00:00 /bin/dd bs 1 if /proc/kmsg of /var/run/klogd/kmsg<br />102 4278 0.0 0.7 3508 2248 Mar20 00:00 /sbin/klogd -P /var/run/klogd/kmsg<br />104 4296 0.0 0.5 2640 844 Mar20 00:02 /bin/dbus-daemon --system<br />0 4315 0.0 1.0 5392 1060 Mar20 00:00 /usr/sbin/sshd<br />0 4349 0.0 1.8 9216 1464 Mar20 00:01 /usr/sbin/winbindd<br />0 4363 0.0 1.8 9472 2000 Mar20 00:00 /usr/sbin/winbindd<br />0 4364 0.0 1.8 9216 1012 Mar20 00:00 /usr/sbin/winbindd<br />0 4365 0.0 0.4 2064 452 Mar20 00:00 /usr/sbin/atd<br />0 4390 0.0 0.7 3408 1016 Mar20 00:00 /usr/sbin/cron<br />0 4400 0.0 1.6 8128 3212 Mar20 00:00 /bin/login --<br />0 4402 0.0 1.8 9216 1108 Mar20 00:00 /usr/sbin/winbindd<br />1000 5213 0.0 1.1 5656 3032 Mar20 00:00 -bash<br />0 5232 0.0 1.6 8144 2316 Mar20 00:00 su -<br />0 5298 0.0 0.8 4220 1832 Mar20 00:00 -su<br />0 5342 0.0 0.4 2252 644 Mar20 00:00 dhclient<br />0 13234 0.0 1.6 8120 1580 00:38 00:02 /usr/sbin/nmbd -D<br />0 13236 0.0 2.6 13604 2816 00:38 00:00 /usr/sbin/smbd -D<br />0 13239 0.0 2.6 13604 1044 00:38 00:00 /usr/sbin/smbd -D<br />0 23643 0.0 2.4 12376 4280 14:43 00:00 sshd: user [priv]<br />1000 23648 0.0 2.4 12512 2008 14:43 00:06 sshd: user@pts/2<br />1000 23649 0.0 1.2 5944 3340 14:43 00:00 -bash<br />0 25860 0.0 1.6 8144 2300 17:55 00:00 su -<br />0 25926 0.0 1.1 5432 3072 17:55 00:00 -su<br />1000 28464 0.0 2.7 13968 4076 21:45 00:00 /usr/sbin/smbd -D<br />0 28655 0.0 1.0 4932 3204 21:58 00:00 python _psutil.py<br />>>><br /></a></pre>
- <h1><a name="Mailing_lists" id="Mailing_lists">Mailing lists</a></h1>
- <p><a name="Mailing_lists" id="Mailing_lists"><strong>Users</strong><br />
- </a><a href="http://groups.google.com/group/psutil/topics" rel="nofollow">http://groups.google.com/group/psutil/topics</a></p>
- <p><strong>Developers</strong><br />
- <a href="http://groups.google.com/group/psutil-dev/topics" rel="nofollow">http://groups.google.com/group/psutil-dev/topics</a></p>
- <p><strong>SVN commits and issue tracker changes</strong><br />
- <a href="http://groups.google.com/group/psutil-commits/topics" rel="nofollow">http://groups.google.com/group/psutil-commits/topics</a></p>
- <p> </p>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<title>psutil - Home</title> +</head> + +<body> +<div id="wikicontent"> + <h1>Python process utilities (psutil)</h1> + <h1><a name="Summary" id="Summary">Summary</a></h1> + <p><a name="Summary" id="Summary">psutil is a module providing an interface for retrieving information on running processes and system utilization (CPU, memory) in a portable way by using Python. </a></p> + <p><a name="Summary" id="Summary">It currently supports Linux, OS X, FreeBSD and Windows. </a></p> + <h1><a name="Example_usage" id="Example_usage">Example usage</a></h1> + <pre><a name="Example_usage" id="Example_usage">>>> import psutil<br />>>> psutil.get_pid_list()<br />[1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224,<br />268, 1215, 1216, 1220, 1221, 1243, 1244, 1301, 1601, 2237, 2355,<br />2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, <br />4263, 4282, 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, <br />4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, 5167, 5234, 5235, <br />5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071]<br />>>> p = psutil.Process(7055)<br />>>> p.name<br />'python'<br />>>> p.path<br />'/usr/bin'<br />>>> p.cmdline<br />['/usr/bin/python', '-O']<br />>>> p.uid<br />1000<br />>>> p.gid<br />1000<br />>>> rss, vms = p.get_memory_info()<br />>>> print "Resident memory: %s KB" %(rss / 1024)<br />Resident memory: 3768 KB<br />>>> print "Virtual memory: %s KB" %(vms / 1024)<br />Virtual memory: 6176 KB<br />>>> <br />>>> psutil.test()<br />UID PID %CPU %MEM VSZ RSS START TIME COMMAND<br />0 0 0.0 0.0 0 0 Mar20 00:00 [sched]<br />0 1 0.0 0.3 1740 600 Mar20 00:04 /sbin/init<br />0 2 0.0 0.0 0 0 Mar20 00:00 [kthreadd]<br />0 3 0.0 0.0 0 0 Mar20 00:00 [migration/0]<br />0 4 0.0 0.0 0 0 Mar20 00:05 [ksoftirqd/0]<br />0 5 0.0 0.0 0 0 Mar20 00:00 [watchdog/0]<br />0 6 0.0 0.0 0 0 Mar20 00:03 [events/0]<br />0 7 0.0 0.0 0 0 Mar20 00:00 [khelper]<br />0 46 0.0 0.0 0 0 Mar20 00:00 [kintegrityd/0]<br />0 48 0.0 0.0 0 0 Mar20 00:01 [kblockd/0]<br />0 50 0.0 0.0 0 0 Mar20 00:00 [kacpid]<br />0 51 0.0 0.0 0 0 Mar20 00:00 [kacpi_notify]<br />0 179 0.0 0.0 0 0 Mar20 00:00 [cqueue]<br />0 183 0.0 0.0 0 0 Mar20 00:00 [kseriod]<br />0 223 0.0 0.0 0 0 Mar20 00:00 [pdflush]<br />0 224 0.0 0.0 0 0 Mar20 00:04 [pdflush]<br />0 225 0.0 0.0 0 0 Mar20 00:01 [kswapd0]<br />0 269 0.0 0.0 0 0 Mar20 00:00 [aio/0]<br />0 1221 0.0 0.0 0 0 Mar20 00:00 [ksuspend_usbd]<br />0 1222 0.0 0.0 0 0 Mar20 00:00 [khubd]<br />0 1226 0.0 0.0 0 0 Mar20 00:00 [ata/0]<br />0 1227 0.0 0.0 0 0 Mar20 00:00 [ata_aux]<br />0 1245 0.0 0.0 0 0 Mar20 00:04 [mpt_poll_0]<br />0 1402 0.0 0.0 0 0 Mar20 00:00 [scsi_eh_0]<br />0 1843 0.0 0.0 0 0 Mar20 00:00 [scsi_eh_1]<br />0 1844 0.0 0.0 0 0 Mar20 00:00 [scsi_eh_2]<br />0 2241 0.0 0.0 0 0 Mar20 00:06 [kjournald]<br />0 2359 0.0 0.4 2312 740 Mar20 00:02 /sbin/udevd --daemon<br />0 2678 0.0 0.0 0 0 Mar20 00:00 [kgameportd]<br />0 2796 0.0 0.0 0 0 Mar20 00:00 [kpsmoused]<br />0 4209 0.0 0.3 1780 536 Mar20 00:00 /sbin/getty 38400 tty4<br />0 4210 0.0 0.3 1780 536 Mar20 00:00 /sbin/getty 38400 tty5<br />0 4215 0.0 0.3 1780 540 Mar20 00:00 /sbin/getty 38400 tty2<br />0 4216 0.0 0.3 1780 540 Mar20 00:00 /sbin/getty 38400 tty3<br />0 4217 0.0 0.3 1780 540 Mar20 00:00 /sbin/getty 38400 tty6<br />101 4258 0.0 0.4 2012 712 Mar20 00:01 /sbin/syslogd -u syslog<br />0 4276 0.0 0.4 1936 544 Mar20 00:00 /bin/dd bs 1 if /proc/kmsg of /var/run/klogd/kmsg<br />102 4278 0.0 0.7 3508 2248 Mar20 00:00 /sbin/klogd -P /var/run/klogd/kmsg<br />104 4296 0.0 0.5 2640 844 Mar20 00:02 /bin/dbus-daemon --system<br />0 4315 0.0 1.0 5392 1060 Mar20 00:00 /usr/sbin/sshd<br />0 4349 0.0 1.8 9216 1464 Mar20 00:01 /usr/sbin/winbindd<br />0 4363 0.0 1.8 9472 2000 Mar20 00:00 /usr/sbin/winbindd<br />0 4364 0.0 1.8 9216 1012 Mar20 00:00 /usr/sbin/winbindd<br />0 4365 0.0 0.4 2064 452 Mar20 00:00 /usr/sbin/atd<br />0 4390 0.0 0.7 3408 1016 Mar20 00:00 /usr/sbin/cron<br />0 4400 0.0 1.6 8128 3212 Mar20 00:00 /bin/login --<br />0 4402 0.0 1.8 9216 1108 Mar20 00:00 /usr/sbin/winbindd<br />1000 5213 0.0 1.1 5656 3032 Mar20 00:00 -bash<br />0 5232 0.0 1.6 8144 2316 Mar20 00:00 su -<br />0 5298 0.0 0.8 4220 1832 Mar20 00:00 -su<br />0 5342 0.0 0.4 2252 644 Mar20 00:00 dhclient<br />0 13234 0.0 1.6 8120 1580 00:38 00:02 /usr/sbin/nmbd -D<br />0 13236 0.0 2.6 13604 2816 00:38 00:00 /usr/sbin/smbd -D<br />0 13239 0.0 2.6 13604 1044 00:38 00:00 /usr/sbin/smbd -D<br />0 23643 0.0 2.4 12376 4280 14:43 00:00 sshd: user [priv]<br />1000 23648 0.0 2.4 12512 2008 14:43 00:06 sshd: user@pts/2<br />1000 23649 0.0 1.2 5944 3340 14:43 00:00 -bash<br />0 25860 0.0 1.6 8144 2300 17:55 00:00 su -<br />0 25926 0.0 1.1 5432 3072 17:55 00:00 -su<br />1000 28464 0.0 2.7 13968 4076 21:45 00:00 /usr/sbin/smbd -D<br />0 28655 0.0 1.0 4932 3204 21:58 00:00 python _psutil.py<br />>>><br /></a></pre> + <h1><a name="Mailing_lists" id="Mailing_lists">Mailing lists</a></h1> + <p><a name="Mailing_lists" id="Mailing_lists"><strong>Users</strong><br /> + </a><a href="http://groups.google.com/group/psutil/topics" rel="nofollow">http://groups.google.com/group/psutil/topics</a></p> + <p><strong>Developers</strong><br /> + <a href="http://groups.google.com/group/psutil-dev/topics" rel="nofollow">http://groups.google.com/group/psutil-dev/topics</a></p> + <p><strong>SVN commits and issue tracker changes</strong><br /> + <a href="http://groups.google.com/group/psutil-commits/topics" rel="nofollow">http://groups.google.com/group/psutil-commits/topics</a></p> + <p> </p> +</div> +</body> +</html> diff --git a/docs/milestones.lnk.html b/docs/milestones.lnk.html index b8cbffa3..83904c8e 100644 --- a/docs/milestones.lnk.html +++ b/docs/milestones.lnk.html @@ -1,12 +1,12 @@ -<html>
-<head>
- <meta http-equiv="refresh" content="2; http://code.google.com/p/psutil/wiki/Milestones">
- <title>Redirecting to Milestones...</title>
-</head>
-
-<body>
-<p>Redirecting to: <a href="http://code.google.com/p/psutil/wiki/Milestones">http://code.google.com/p/psutil/wiki/Milestones</a><br></p>
-<p>You'll be redirected in 2 seconds...</p>
-
-</body>
-</html>
+<html> +<head> + <meta http-equiv="refresh" content="2; http://code.google.com/p/psutil/wiki/Milestones"> + <title>Redirecting to Milestones...</title> +</head> + +<body> +<p>Redirecting to: <a href="http://code.google.com/p/psutil/wiki/Milestones">http://code.google.com/p/psutil/wiki/Milestones</a><br></p> +<p>You'll be redirected in 2 seconds...</p> + +</body> +</html> diff --git a/psutil/arch/mswindows/process_handles.c b/psutil/arch/mswindows/process_handles.c index f5a50a93..ec9c6337 100644 --- a/psutil/arch/mswindows/process_handles.c +++ b/psutil/arch/mswindows/process_handles.c @@ -1,295 +1,295 @@ -#ifndef UNICODE
-#define UNICODE
-#endif
-
-#include <Python.h>
-#include <windows.h>
-#include <stdio.h>
-#include <Ntdef.h>
-#include "process_handles.h"
-
-#ifndef NT_SUCCESS
- #define NT_SUCCESS(x) ((x) >= 0)
-#endif
-#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004
-
-#define SystemHandleInformation 16
-#define ObjectBasicInformation 0
-#define ObjectNameInformation 1
-#define ObjectTypeInformation 2
-
-typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)(
- ULONG SystemInformationClass,
- PVOID SystemInformation,
- ULONG SystemInformationLength,
- PULONG ReturnLength
- );
-
-typedef NTSTATUS (NTAPI *_NtDuplicateObject)(
- HANDLE SourceProcessHandle,
- HANDLE SourceHandle,
- HANDLE TargetProcessHandle,
- PHANDLE TargetHandle,
- ACCESS_MASK DesiredAccess,
- ULONG Attributes,
- ULONG Options
- );
-
-typedef NTSTATUS (NTAPI *_NtQueryObject)(
- HANDLE ObjectHandle,
- ULONG ObjectInformationClass,
- PVOID ObjectInformation,
- ULONG ObjectInformationLength,
- PULONG ReturnLength
- );
-
-typedef struct _SYSTEM_HANDLE
-{
- ULONG ProcessId;
- BYTE ObjectTypeNumber;
- BYTE Flags;
- USHORT Handle;
- PVOID Object;
- ACCESS_MASK GrantedAccess;
-} SYSTEM_HANDLE, *PSYSTEM_HANDLE;
-
-typedef struct _SYSTEM_HANDLE_INFORMATION
-{
- ULONG HandleCount;
- SYSTEM_HANDLE Handles[1];
-} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
-
-typedef enum _POOL_TYPE
-{
- NonPagedPool,
- PagedPool,
- NonPagedPoolMustSucceed,
- DontUseThisType,
- NonPagedPoolCacheAligned,
- PagedPoolCacheAligned,
- NonPagedPoolCacheAlignedMustS
-} POOL_TYPE, *PPOOL_TYPE;
-
-typedef struct _OBJECT_TYPE_INFORMATION
-{
- UNICODE_STRING Name;
- ULONG TotalNumberOfObjects;
- ULONG TotalNumberOfHandles;
- ULONG TotalPagedPoolUsage;
- ULONG TotalNonPagedPoolUsage;
- ULONG TotalNamePoolUsage;
- ULONG TotalHandleTableUsage;
- ULONG HighWaterNumberOfObjects;
- ULONG HighWaterNumberOfHandles;
- ULONG HighWaterPagedPoolUsage;
- ULONG HighWaterNonPagedPoolUsage;
- ULONG HighWaterNamePoolUsage;
- ULONG HighWaterHandleTableUsage;
- ULONG InvalidAttributes;
- GENERIC_MAPPING GenericMapping;
- ULONG ValidAccess;
- BOOLEAN SecurityRequired;
- BOOLEAN MaintainHandleCount;
- USHORT MaintainTypeList;
- POOL_TYPE PoolType;
- ULONG PagedPoolUsage;
- ULONG NonPagedPoolUsage;
-} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
-
-PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
-{
- return GetProcAddress(GetModuleHandleA(LibraryName), ProcName);
-}
-
-
-PyObject* get_open_files(long pid, HANDLE processHandle)
-{
- _NtQuerySystemInformation NtQuerySystemInformation =
- GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
- _NtDuplicateObject NtDuplicateObject =
- GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject");
- _NtQueryObject NtQueryObject =
- GetLibraryProcAddress("ntdll.dll", "NtQueryObject");
-
- NTSTATUS status;
- PSYSTEM_HANDLE_INFORMATION handleInfo;
- ULONG handleInfoSize = 0x10000;
-
- ULONG i;
- ULONG fileNameLength;
- PyObject *filesList = Py_BuildValue("[]");
- PyObject *arg = NULL;
- PyObject *fileFromWchar = NULL;
-
-
-
- handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
-
- /* NtQuerySystemInformation won't give us the correct buffer size,
- so we guess by doubling the buffer size. */
- while ((status = NtQuerySystemInformation(
- SystemHandleInformation,
- handleInfo,
- handleInfoSize,
- NULL
- )) == STATUS_INFO_LENGTH_MISMATCH)
- handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2);
-
- /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */
- if (!NT_SUCCESS(status)) {
- //printf("NtQuerySystemInformation failed!\n");
- return NULL;
- }
-
- for (i = 0; i < handleInfo->HandleCount; i++)
- {
- SYSTEM_HANDLE handle = handleInfo->Handles[i];
- HANDLE dupHandle = NULL;
- POBJECT_TYPE_INFORMATION objectTypeInfo;
- PVOID objectNameInfo;
- UNICODE_STRING objectName;
- ULONG returnLength;
-
- /* Check if this handle belongs to the PID the user specified. */
- if (handle.ProcessId != pid)
- continue;
-
- /* Duplicate the handle so we can query it. */
- if (!NT_SUCCESS(NtDuplicateObject(
- processHandle,
- handle.Handle,
- GetCurrentProcess(),
- &dupHandle,
- 0,
- 0,
- 0
- )))
- {
- //printf("[%#x] Error!\n", handle.Handle);
- continue;
- }
-
- /* Query the object type. */
- objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000);
- if (!NT_SUCCESS(NtQueryObject(
- dupHandle,
- ObjectTypeInformation,
- objectTypeInfo,
- 0x1000,
- NULL
- )))
- {
- //printf("[%#x] Error!\n", handle.Handle);
- CloseHandle(dupHandle);
- continue;
- }
-
- /* Query the object name (unless it has an access of
- 0x0012019f, on which NtQueryObject could hang. */
- if (handle.GrantedAccess == 0x0012019f)
- {
- /* We have the type, so display that. */
- /*
- printf(
- "[%#x] %.*S: (did not get name)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- */
- free(objectTypeInfo);
- CloseHandle(dupHandle);
- continue;
- }
-
- objectNameInfo = malloc(0x1000);
- if (!NT_SUCCESS(NtQueryObject(
- dupHandle,
- ObjectNameInformation,
- objectNameInfo,
- 0x1000,
- &returnLength
- )))
- {
- /* Reallocate the buffer and try again. */
- objectNameInfo = realloc(objectNameInfo, returnLength);
- if (!NT_SUCCESS(NtQueryObject(
- dupHandle,
- ObjectNameInformation,
- objectNameInfo,
- returnLength,
- NULL
- )))
- {
- /* We have the type name, so just display that.*/
- /*
- printf(
- "[%#x] %.*S: (could not get name)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- */
- free(objectTypeInfo);
- free(objectNameInfo);
- CloseHandle(dupHandle);
- continue;
-
- }
- }
-
- /* Cast our buffer into an UNICODE_STRING. */
- objectName = *(PUNICODE_STRING)objectNameInfo;
-
- /* Print the information! */
- if (objectName.Length)
- {
- /* The object has a name. Make sure it is a file otherwise
- ignore it */
- fileNameLength = objectName.Length / 2;
- if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) {
- //printf("%.*S\n", objectName.Length / 2, objectName.Buffer);
- fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer,
- fileNameLength);
- #if PY_MAJOR_VERSION >= 3
- arg = Py_BuildValue("N", PyUnicode_AsUTF8String(fileFromWchar));
- #else
- arg = Py_BuildValue("N", PyUnicode_FromObject(fileFromWchar));
- #endif
- Py_XDECREF(fileFromWchar);
- PyList_Append(filesList, arg);
- Py_XDECREF(arg);
- }
- /*
- printf(
- "[%#x] %.*S: %.*S\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer,
- objectName.Length / 2,
- objectName.Buffer
- );
- */
- }
- else
- {
- /* Print something else. */
- /*
- printf(
- "[%#x] %.*S: (unnamed)\n",
- handle.Handle,
- objectTypeInfo->Name.Length / 2,
- objectTypeInfo->Name.Buffer
- );
- */
- ;;
- }
- free(objectTypeInfo);
- free(objectNameInfo);
- CloseHandle(dupHandle);
- }
- free(handleInfo);
- CloseHandle(processHandle);
- return filesList;
-}
-
+#ifndef UNICODE +#define UNICODE +#endif + +#include <Python.h> +#include <windows.h> +#include <stdio.h> +#include <Ntdef.h> +#include "process_handles.h" + +#ifndef NT_SUCCESS + #define NT_SUCCESS(x) ((x) >= 0) +#endif +#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 + +#define SystemHandleInformation 16 +#define ObjectBasicInformation 0 +#define ObjectNameInformation 1 +#define ObjectTypeInformation 2 + +typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)( + ULONG SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength + ); + +typedef NTSTATUS (NTAPI *_NtDuplicateObject)( + HANDLE SourceProcessHandle, + HANDLE SourceHandle, + HANDLE TargetProcessHandle, + PHANDLE TargetHandle, + ACCESS_MASK DesiredAccess, + ULONG Attributes, + ULONG Options + ); + +typedef NTSTATUS (NTAPI *_NtQueryObject)( + HANDLE ObjectHandle, + ULONG ObjectInformationClass, + PVOID ObjectInformation, + ULONG ObjectInformationLength, + PULONG ReturnLength + ); + +typedef struct _SYSTEM_HANDLE +{ + ULONG ProcessId; + BYTE ObjectTypeNumber; + BYTE Flags; + USHORT Handle; + PVOID Object; + ACCESS_MASK GrantedAccess; +} SYSTEM_HANDLE, *PSYSTEM_HANDLE; + +typedef struct _SYSTEM_HANDLE_INFORMATION +{ + ULONG HandleCount; + SYSTEM_HANDLE Handles[1]; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +typedef enum _POOL_TYPE +{ + NonPagedPool, + PagedPool, + NonPagedPoolMustSucceed, + DontUseThisType, + NonPagedPoolCacheAligned, + PagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS +} POOL_TYPE, *PPOOL_TYPE; + +typedef struct _OBJECT_TYPE_INFORMATION +{ + UNICODE_STRING Name; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + ULONG HighWaterPagedPoolUsage; + ULONG HighWaterNonPagedPoolUsage; + ULONG HighWaterNamePoolUsage; + ULONG HighWaterHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccess; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + USHORT MaintainTypeList; + POOL_TYPE PoolType; + ULONG PagedPoolUsage; + ULONG NonPagedPoolUsage; +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + +PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName) +{ + return GetProcAddress(GetModuleHandleA(LibraryName), ProcName); +} + + +PyObject* get_open_files(long pid, HANDLE processHandle) +{ + _NtQuerySystemInformation NtQuerySystemInformation = + GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); + _NtDuplicateObject NtDuplicateObject = + GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); + _NtQueryObject NtQueryObject = + GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); + + NTSTATUS status; + PSYSTEM_HANDLE_INFORMATION handleInfo; + ULONG handleInfoSize = 0x10000; + + ULONG i; + ULONG fileNameLength; + PyObject *filesList = Py_BuildValue("[]"); + PyObject *arg = NULL; + PyObject *fileFromWchar = NULL; + + + + handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); + + /* NtQuerySystemInformation won't give us the correct buffer size, + so we guess by doubling the buffer size. */ + while ((status = NtQuerySystemInformation( + SystemHandleInformation, + handleInfo, + handleInfoSize, + NULL + )) == STATUS_INFO_LENGTH_MISMATCH) + handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); + + /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ + if (!NT_SUCCESS(status)) { + //printf("NtQuerySystemInformation failed!\n"); + return NULL; + } + + for (i = 0; i < handleInfo->HandleCount; i++) + { + SYSTEM_HANDLE handle = handleInfo->Handles[i]; + HANDLE dupHandle = NULL; + POBJECT_TYPE_INFORMATION objectTypeInfo; + PVOID objectNameInfo; + UNICODE_STRING objectName; + ULONG returnLength; + + /* Check if this handle belongs to the PID the user specified. */ + if (handle.ProcessId != pid) + continue; + + /* Duplicate the handle so we can query it. */ + if (!NT_SUCCESS(NtDuplicateObject( + processHandle, + handle.Handle, + GetCurrentProcess(), + &dupHandle, + 0, + 0, + 0 + ))) + { + //printf("[%#x] Error!\n", handle.Handle); + continue; + } + + /* Query the object type. */ + objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectTypeInformation, + objectTypeInfo, + 0x1000, + NULL + ))) + { + //printf("[%#x] Error!\n", handle.Handle); + CloseHandle(dupHandle); + continue; + } + + /* Query the object name (unless it has an access of + 0x0012019f, on which NtQueryObject could hang. */ + if (handle.GrantedAccess == 0x0012019f) + { + /* We have the type, so display that. */ + /* + printf( + "[%#x] %.*S: (did not get name)\n", + handle.Handle, + objectTypeInfo->Name.Length / 2, + objectTypeInfo->Name.Buffer + ); + */ + free(objectTypeInfo); + CloseHandle(dupHandle); + continue; + } + + objectNameInfo = malloc(0x1000); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectNameInformation, + objectNameInfo, + 0x1000, + &returnLength + ))) + { + /* Reallocate the buffer and try again. */ + objectNameInfo = realloc(objectNameInfo, returnLength); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectNameInformation, + objectNameInfo, + returnLength, + NULL + ))) + { + /* We have the type name, so just display that.*/ + /* + printf( + "[%#x] %.*S: (could not get name)\n", + handle.Handle, + objectTypeInfo->Name.Length / 2, + objectTypeInfo->Name.Buffer + ); + */ + free(objectTypeInfo); + free(objectNameInfo); + CloseHandle(dupHandle); + continue; + + } + } + + /* Cast our buffer into an UNICODE_STRING. */ + objectName = *(PUNICODE_STRING)objectNameInfo; + + /* Print the information! */ + if (objectName.Length) + { + /* The object has a name. Make sure it is a file otherwise + ignore it */ + fileNameLength = objectName.Length / 2; + if (wcscmp(objectTypeInfo->Name.Buffer, L"File") == 0) { + //printf("%.*S\n", objectName.Length / 2, objectName.Buffer); + fileFromWchar = PyUnicode_FromWideChar(objectName.Buffer, + fileNameLength); + #if PY_MAJOR_VERSION >= 3 + arg = Py_BuildValue("N", PyUnicode_AsUTF8String(fileFromWchar)); + #else + arg = Py_BuildValue("N", PyUnicode_FromObject(fileFromWchar)); + #endif + Py_XDECREF(fileFromWchar); + PyList_Append(filesList, arg); + Py_XDECREF(arg); + } + /* + printf( + "[%#x] %.*S: %.*S\n", + handle.Handle, + objectTypeInfo->Name.Length / 2, + objectTypeInfo->Name.Buffer, + objectName.Length / 2, + objectName.Buffer + ); + */ + } + else + { + /* Print something else. */ + /* + printf( + "[%#x] %.*S: (unnamed)\n", + handle.Handle, + objectTypeInfo->Name.Length / 2, + objectTypeInfo->Name.Buffer + ); + */ + ;; + } + free(objectTypeInfo); + free(objectNameInfo); + CloseHandle(dupHandle); + } + free(handleInfo); + CloseHandle(processHandle); + return filesList; +} + diff --git a/psutil/arch/mswindows/process_handles.h b/psutil/arch/mswindows/process_handles.h index cbbb2ba8..bd9d39b8 100644 --- a/psutil/arch/mswindows/process_handles.h +++ b/psutil/arch/mswindows/process_handles.h @@ -1,4 +1,4 @@ -#include <Python.h>
-#include <windows.h>
-
-PyObject* get_open_files(long pid, HANDLE processHandle);
+#include <Python.h> +#include <windows.h> + +PyObject* get_open_files(long pid, HANDLE processHandle); diff --git a/psutil/wmi.py b/psutil/wmi.py index 74d4a024..70324dca 100644 --- a/psutil/wmi.py +++ b/psutil/wmi.py @@ -1,1418 +1,1418 @@ -"""
-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 :class:`_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.
-"""
-__VERSION__ = __version__ = "1.4.6"
-
-_DEBUG = False
-
-import sys
-import datetime
-import re
-import struct
-import warnings
-
-from win32com.client import GetObject, Dispatch
-import pywintypes
-
-def signed_to_unsigned (signed):
- """Convert a (possibly signed) long to unsigned hex. Useful
- when converting a COM error code to the more conventional
- 8-digit hex::
-
- print "%08X" % signed_to_unsigned (-2147023174)
- """
- unsigned, = struct.unpack ("L", struct.pack ("l", signed))
- return unsigned
-
-class SelfDeprecatingDict (object):
- """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`.
- """
-
- dict_only = set (dir (dict)).difference (dir (list))
-
- def __init__ (self, dictlike):
- self.dict = dict (dictlike)
- self.list = list (self.dict)
-
- def __getattr__ (self, attribute):
- if attribute in self.dict_only:
- warnings.warn ("In future this will be a list and not a dictionary", DeprecationWarning)
- return getattr (self.dict, attribute)
- else:
- return getattr (self.list, attribute)
-
- def __iter__ (self):
- return iter (self.list)
-
- def __str__ (self):
- return str (self.list)
-
- def __repr__ (self):
- return repr (self.list)
-
- def __getitem__ (self, item):
- try:
- return self.list[item]
- except TypeError:
- return self.dict[item]
-
-class ProvideConstants (object):
- """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 :attr:`_constants`
- property. (From Thomas Heller on c.l.py).
- """
- def __init__(self, comobj):
- comobj.__dict__["_constants"] = self
- self.__typecomp = \
- comobj._oleobj_.GetTypeInfo().GetContainingTypeLib()[0].GetTypeComp()
-
- def __getattr__(self, name):
- if name.startswith("__") and name.endswith("__"):
- raise AttributeError (name)
- result = self.__typecomp.Bind(name)
- if not result[0]:
- raise AttributeError (name)
- return result[1].value
-
-obj = GetObject ("winmgmts:")
-ProvideConstants (obj)
-
-wbemErrInvalidQuery = obj._constants.wbemErrInvalidQuery
-wbemErrTimedout = obj._constants.wbemErrTimedout
-wbemFlagReturnImmediately = obj._constants.wbemFlagReturnImmediately
-wbemFlagForwardOnly = obj._constants.wbemFlagForwardOnly
-
-#
-# Exceptions
-#
-class x_wmi (Exception):
- """Ancestor of all wmi-related exceptions. Keeps track of
- an info message and the underlying COM error if any, exposed
- as the :attr:`com_error` attribute.
- """
- def __init__ (self, info="", com_error=None):
- self.info = info
- self.com_error = com_error
-
- def __str__ (self):
- return "<x_wmi: %s %s>" % (
- self.info or "Unexpected COM Error",
- self.com_error or "(no underlying exception)"
- )
-
-class x_wmi_invalid_query (x_wmi):
- "Raised when a WMI returns `wbemErrInvalidQuery`"
- pass
-
-class x_wmi_timed_out (x_wmi):
- "Raised when a watcher times out"
- pass
-
-class x_wmi_no_namespace (x_wmi):
- """Raised when an attempt is made to query or watch
- from a class without a namespace.
- """
- pass
-
-class x_access_denied (x_wmi):
- "Raised when WMI raises 80070005"
- pass
-
-class x_wmi_authentication (x_wmi):
- "Raised when an invalid combination of authentication properties is attempted when connecting"
- pass
-
-class x_wmi_uninitialised_thread (x_wmi):
- """Raised when WMI returns 800401E4 on connection, usually
- indicating that no COM threading model has been initialised
- """
- pass
-
-WMI_EXCEPTIONS = {
- signed_to_unsigned (wbemErrInvalidQuery) : x_wmi_invalid_query,
- signed_to_unsigned (wbemErrTimedout) : x_wmi_timed_out,
- 0x80070005 : x_access_denied,
- 0x80041003 : x_access_denied,
- 0x800401E4 : x_wmi_uninitialised_thread,
-}
-
-def handle_com_error (err=None):
- """Convenience wrapper for displaying all manner of COM errors.
- Raises a :exc:`x_wmi` exception with more useful information attached
-
- :param err: The structure attached to a `pywintypes.com_error`
- """
- if err is None:
- _, err, _ = sys.exc_info ()
- hresult_code, hresult_name, additional_info, parameter_in_error = err.args
- hresult_code = signed_to_unsigned (hresult_code)
- exception_string = ["%s - %s" % (hex (hresult_code), hresult_name)]
- scode = None
- if additional_info:
- wcode, source_of_error, error_description, whlp_file, whlp_context, scode = additional_info
- scode = signed_to_unsigned (scode)
- exception_string.append (" Error in: %s" % source_of_error)
- exception_string.append (" %s - %s" % (hex (scode), (error_description or "").strip ()))
- for error_code, klass in WMI_EXCEPTIONS.items ():
- if error_code in (hresult_code, scode):
- break
- else:
- klass = x_wmi
- raise klass (com_error=err)
-
-
-BASE = datetime.datetime (1601, 1, 1)
-def from_1601 (ns100):
- return BASE + datetime.timedelta (microseconds=int (ns100) / 10)
-
-def 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.
-
- :param year: The year element of the date/time
- :param month: The month element of the date/time
- :param day: The day element of the date/time
- :param hours: The hours element of the date/time
- :param minutes: The minutes element of the date/time
- :param seconds: The seconds element of the date/time
- :param microseconds: The microseconds element of the date/time
- :param timezone: The timeezone element of the date/time
-
- :returns: A WMI datetime string of the form: `yyyymmddHHMMSS.mmmmmm+UUU`
- """
- def str_or_stars (i, length):
- if i is None:
- return "*" * length
- else:
- return str (i).rjust (length, "0")
-
- wmi_time = ""
- wmi_time += str_or_stars (year, 4)
- wmi_time += str_or_stars (month, 2)
- wmi_time += str_or_stars (day, 2)
- wmi_time += str_or_stars (hours, 2)
- wmi_time += str_or_stars (minutes, 2)
- wmi_time += str_or_stars (seconds, 2)
- wmi_time += "."
- wmi_time += str_or_stars (microseconds, 6)
- wmi_time += "+"
- wmi_time += str_or_stars (timezone, 3)
-
- return wmi_time
-
-def 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.
-
- :param wmi_time: The WMI datetime string in `yyyymmddHHMMSS.mmmmmm+UUU` format
-
- :returns: A 9-tuple of (year, month, day, hours, minutes, seconds, microseconds, timezone)
- """
- def int_or_none (s, start, end):
- try:
- return int (s[start:end])
- except ValueError:
- return None
-
- year = int_or_none (wmi_time, 0, 4)
- month = int_or_none (wmi_time, 4, 6)
- day = int_or_none (wmi_time, 6, 8)
- hours = int_or_none (wmi_time, 8, 10)
- minutes = int_or_none (wmi_time, 10, 12)
- seconds = int_or_none (wmi_time, 12, 14)
- microseconds = int_or_none (wmi_time, 15, 21)
- timezone = wmi_time[22:]
- if timezone == "***":
- timezone = None
-
- return year, month, day, hours, minutes, seconds, microseconds, timezone
-
-def _set (obj, attribute, value):
- """Helper function to add an attribute directly into the instance
- dictionary, bypassing possible `__getattr__` calls
-
- :param obj: Any python object
- :param attribute: String containing attribute name
- :param value: Any python object
- """
- obj.__dict__[attribute] = value
-
-class _wmi_method:
- """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.
- """
-
- def __init__ (self, ole_object, method_name):
- """
- :param ole_object: The WMI class/instance whose method is to be called
- :param method_name: The name of the method to be called
- """
- try:
- self.ole_object = Dispatch (ole_object)
- self.method = ole_object.Methods_ (method_name)
- self.qualifiers = {}
- for q in self.method.Qualifiers_:
- self.qualifiers[q.Name] = q.Value
- self.provenance = "\n".join (self.qualifiers.get ("MappingStrings", []))
-
- self.in_parameters = self.method.InParameters
- self.out_parameters = self.method.OutParameters
- if self.in_parameters is None:
- self.in_parameter_names = []
- else:
- self.in_parameter_names = [(i.Name, i.IsArray) for i in self.in_parameters.Properties_]
- if self.out_parameters is None:
- self.out_parameter_names = []
- else:
- self.out_parameter_names = [(i.Name, i.IsArray) for i in self.out_parameters.Properties_]
-
- doc = "%s (%s) => (%s)" % (
- method_name,
- ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.in_parameter_names]),
- ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.out_parameter_names])
- )
- privileges = self.qualifiers.get ("Privileges", [])
- if privileges:
- doc += " | Needs: " + ", ".join (privileges)
- self.__doc__ = doc
- except pywintypes.com_error:
- handle_com_error ()
-
- def __call__ (self, *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.
- """
- try:
- if self.in_parameters:
- parameter_names = {}
- for name, is_array in self.in_parameter_names:
- parameter_names[name] = is_array
-
- parameters = self.in_parameters
-
- #
- # Check positional parameters first
- #
- for n_arg in range (len (args)):
- arg = args[n_arg]
- parameter = parameters.Properties_[n_arg]
- if parameter.IsArray:
- try: list (arg)
- except TypeError: raise TypeError ("parameter %d must be iterable" % n_arg)
- parameter.Value = arg
-
- #
- # If any keyword param supersedes a positional one,
- # it'll simply overwrite it.
- #
- for k, v in kwargs.items ():
- is_array = parameter_names.get (k)
- if is_array is None:
- raise AttributeError ("%s is not a valid parameter for %s" % (k, self.__doc__))
- else:
- if is_array:
- try: list (v)
- except TypeError: raise TypeError ("%s must be iterable" % k)
- parameters.Properties_ (k).Value = v
-
- result = self.ole_object.ExecMethod_ (self.method.Name, self.in_parameters)
- else:
- result = self.ole_object.ExecMethod_ (self.method.Name)
-
- results = []
- for name, is_array in self.out_parameter_names:
- value = result.Properties_ (name).Value
- if is_array:
- #
- # Thanks to Jonas Bjering for bug report and patch
- #
- results.append (list (value or []))
- else:
- results.append (value)
- return tuple (results)
-
- except pywintypes.com_error:
- handle_com_error ()
-
- def __repr__ (self):
- return "<function %s>" % self.__doc__
-
-class _wmi_property (object):
-
- def __init__ (self, property):
- self.property = property
- self.name = property.Name
- self.value = property.Value
- self.qualifiers = dict ((q.Name, q.Value) for q in property.Qualifiers_)
- self.type = self.qualifiers.get ("CIMTYPE", None)
-
- def set (self, value):
- self.property.Value = value
-
- def __getattr__ (self, attr):
- return getattr (self.property, attr)
-
-#
-# class _wmi_object
-#
-class _wmi_object:
- """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 :class:`_wmi_class`
- on the parent :class:`_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
- """
-
- def __init__ (self, ole_object, instance_of=None, fields=[], property_map={}):
- try:
- _set (self, "ole_object", ole_object)
- _set (self, "id", ole_object.Path_.DisplayName.lower ())
- _set (self, "_instance_of", instance_of)
- _set (self, "properties", {})
- _set (self, "methods", {})
- _set (self, "property_map", property_map)
- _set (self, "_associated_classes", None)
- _set (self, "_keys", None)
-
- if fields:
- for field in fields:
- self.properties[field] = None
- else:
- for p in ole_object.Properties_:
- self.properties[p.Name] = None
-
- for m in ole_object.Methods_:
- self.methods[m.Name] = None
-
- _set (self, "_properties", self.properties.keys ())
- _set (self, "_methods", self.methods.keys ())
- _set (self, "qualifiers", dict ((q.Name, q.Value) for q in self.ole_object.Qualifiers_))
-
- except pywintypes.com_error:
- handle_com_error ()
-
- def __lt__ (self, other):
- return self.id < other.id
-
- def __str__ (self):
- """For a call to print [object] return the OLE description
- of the properties / values of the object
- """
- try:
- return self.ole_object.GetObjectText_ ()
- except pywintypes.com_error:
- handle_com_error ()
-
- def __repr__ (self):
- """
- Indicate both the fact that this is a wrapped WMI object
- and the WMI object's own identifying class.
- """
- try:
- return "<%s: %s>" % (self.__class__.__name__, str (self.Path_.Path))
- except pywintypes.com_error:
- handle_com_error ()
-
- def _cached_properties (self, attribute):
- if self.properties[attribute] is None:
- self.properties[attribute] = _wmi_property (self.ole_object.Properties_ (attribute))
- return self.properties[attribute]
-
- def _cached_methods (self, attribute):
- if self.methods[attribute] is None:
- self.methods[attribute] = _wmi_method (self.ole_object, attribute)
- return self.methods[attribute]
-
- def __getattr__ (self, attribute):
- """
- Attempt to pass attribute calls to the proxied COM object.
- If the attribute is recognised as a property, return its value;
- if it is recognised as a method, return a method wrapper which
- can then be called with parameters; otherwise pass the lookup
- on to the underlying object.
- """
- try:
- if attribute in self.properties:
- property = self._cached_properties (attribute)
- factory = self.property_map.get (attribute, self.property_map.get (property.type, lambda x: x))
- value = factory (property.value)
- #
- # If this is an association, certain of its properties
- # are actually the paths to the aspects of the association,
- # so translate them automatically into WMI objects.
- #
- if property.type.startswith ("ref:"):
- return WMI (moniker=value)
- else:
- return value
- elif attribute in self.methods:
- return self._cached_methods (attribute)
- else:
- return getattr (self.ole_object, attribute)
- except pywintypes.com_error:
- handle_com_error ()
-
- def __setattr__ (self, attribute, value):
- """If the attribute to be set is valid for the proxied
- COM object, set that objects's parameter value; if not,
- raise an exception.
- """
- try:
- if attribute in self.properties:
- self._cached_properties (attribute).set (value)
- if self.ole_object.Path_.Path:
- self.ole_object.Put_ ()
- else:
- raise AttributeError (attribute)
- except pywintypes.com_error:
- handle_com_error ()
-
- def __eq__ (self, other):
- return self.id == other.id
-
- def __hash__ (self):
- return hash (self.id)
-
- def _getAttributeNames (self):
- """Return list of methods/properties for IPython completion"""
- attribs = [str (x) for x in self.methods.keys ()]
- attribs.extend ([str (x) for x in self.properties.keys ()])
- return attribs
-
- def _get_keys (self):
- """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
- """
- # NB You can get the keys of an instance more directly, via
- # Path\_.Keys but this doesn't apply to classes. The technique
- # here appears to work for both.
- if self._keys is None:
- _set (self, "_keys", [])
- for property in self.ole_object.Properties_:
- for qualifier in property.Qualifiers_:
- if qualifier.Name == "key" and qualifier.Value:
- self._keys.append (property.Name)
- return self._keys
- keys = property (_get_keys)
-
- def put (self):
- """Push all outstanding property updates back to the
- WMI database.
- """
- self.ole_object.Put_ ()
-
- def set (self, **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.
- """
- if kwargs:
- try:
- for attribute, value in kwargs.items ():
- if attribute in self.properties:
- self._cached_properties (attribute).set (value)
- else:
- raise AttributeError (attribute)
- #
- # Only try to write the attributes
- # back if the object exists.
- #
- if self.ole_object.Path_.Path:
- self.ole_object.Put_ ()
- except pywintypes.com_error:
- handle_com_error ()
-
- def path (self):
- """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
-
- .. Do more with this
- """
- try:
- return self.ole_object.Path_
- except pywintypes.com_error:
- handle_com_error ()
-
- def derivation (self):
- """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 ())
- """
- try:
- return self.ole_object.Derivation_
- except pywintypes.com_error:
- handle_com_error ()
-
- def _cached_associated_classes (self):
- if self._associated_classes is None:
- if isinstance (self, _wmi_class):
- params = {'bSchemaOnly' : True}
- else:
- params = {'bClassesOnly' : True}
- try:
- associated_classes = dict (
- (assoc.Path_.Class, _wmi_class (self._namespace, assoc)) for
- assoc in self.ole_object.Associators_ (**params)
- )
- _set (self, "_associated_classes", associated_classes)
- except pywintypes.com_error:
- handle_com_error ()
-
- return self._associated_classes
- associated_classes = property (_cached_associated_classes)
-
- def associators (self, 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
- """
- try:
- return [
- _wmi_object (i) for i in \
- self.ole_object.Associators_ (
- strAssocClass=wmi_association_class,
- strResultClass=wmi_result_class
- )
- ]
- except pywintypes.com_error:
- handle_com_error ()
-
- def references (self, 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
- """
- #
- # FIXME: Allow an actual class to be passed in, using
- # its .Path_.RelPath property to determine the string
- #
- try:
- return [_wmi_object (i) for i in self.ole_object.References_ (strResultClass=wmi_class)]
- except pywintypes.com_error:
- handle_com_error ()
-
-#
-# class _wmi_event
-#
-class _wmi_event (_wmi_object):
- """Slight extension of the _wmi_object class to allow
- objects which are the result of events firing to return
- extra information such as the type of event.
- """
- event_type_re = re.compile ("__Instance(Creation|Modification|Deletion)Event")
- def __init__ (self, event, event_info, fields=[]):
- _wmi_object.__init__ (self, event, fields=fields)
- _set (self, "event_type", None)
- _set (self, "timestamp", None)
- _set (self, "previous", None)
-
- if event_info:
- event_type = self.event_type_re.match (event_info.Path_.Class).group (1).lower ()
- _set (self, "event_type", event_type)
- if hasattr (event_info, "TIME_CREATED"):
- _set (self, "timestamp", from_1601 (event_info.TIME_CREATED))
- if hasattr (event_info, "PreviousInstance"):
- _set (self, "previous", event_info.PreviousInstance)
-
-#
-# class _wmi_class
-#
-class _wmi_class (_wmi_object):
- """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:')
- """
- def __init__ (self, namespace, wmi_class):
- _wmi_object.__init__ (self, wmi_class)
- _set (self, "_class_name", wmi_class.Path_.Class)
- if namespace:
- _set (self, "_namespace", namespace)
- else:
- class_moniker = wmi_class.Path_.DisplayName
- winmgmts, namespace_moniker, class_name = class_moniker.split (":")
- namespace = _wmi_namespace (GetObject (winmgmts + ":" + namespace_moniker), False)
- _set (self, "_namespace", namespace)
-
- def query (self, 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.
- """
- #
- # FIXME: Not clear if this can ever happen
- #
- if self._namespace is None:
- raise x_wmi_no_namespace ("You cannot query directly from a WMI class")
-
- try:
- field_list = ", ".join (fields) or "*"
- wql = "SELECT " + field_list + " FROM " + self._class_name
- if where_clause:
- wql += " WHERE " + " AND ". join (["%s = '%s'" % (k, v) for k, v in where_clause.items ()])
- return self._namespace.query (wql, self, fields)
- except pywintypes.com_error:
- handle_com_error ()
-
- __call__ = query
-
- def watch_for (
- self,
- notification_type="operation",
- delay_secs=1,
- fields=[],
- **where_clause
- ):
- if self._namespace is None:
- raise x_wmi_no_namespace ("You cannot watch directly from a WMI class")
-
- valid_notification_types = ("operation", "creation", "deletion", "modification")
- if notification_type.lower () not in valid_notification_types:
- raise x_wmi ("notification_type must be one of %s" % ", ".join (valid_notification_types))
-
- return self._namespace.watch_for (
- notification_type=notification_type,
- wmi_class=self,
- delay_secs=delay_secs,
- fields=fields,
- **where_clause
- )
-
- def instances (self):
- """Return a list of instances of the WMI class
- """
- try:
- return [_wmi_object (instance, self) for instance in self.Instances_ ()]
- except pywintypes.com_error:
- handle_com_error ()
-
- def new (self, **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.
- """
- try:
- obj = _wmi_object (self.SpawnInstance_ (), self)
- obj.set (**kwargs)
- return obj
- except pywintypes.com_error:
- handle_com_error ()
-
-#
-# class _wmi_result
-#
-class _wmi_result:
- """Simple, data only result for targeted WMI queries which request
- data only result classes via fetch_as_classes.
- """
- def __init__(self, obj, attributes):
- if attributes:
- for attr in attributes:
- self.__dict__[attr] = obj.Properties_ (attr).Value
- else:
- for p in obj.Properties_:
- attr = p.Name
- self.__dict__[attr] = obj.Properties_(attr).Value
-
-#
-# class WMI
-#
-class _wmi_namespace:
- """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
- """
- def __init__ (self, namespace, find_classes):
- _set (self, "_namespace", namespace)
- #
- # wmi attribute preserved for backwards compatibility
- #
- _set (self, "wmi", namespace)
-
- self._classes = None
- self._classes_map = {}
- #
- # Pick up the list of classes under this namespace
- # so that they can be queried, and used as though
- # properties of the namespace by means of the __getattr__
- # hook below.
- # If the namespace does not support SubclassesOf, carry on
- # regardless
- #
- if find_classes:
- _ = self.classes
-
- def __repr__ (self):
- return "<_wmi_namespace: %s>" % self.wmi
-
- def __str__ (self):
- return repr (self)
-
- def _get_classes (self):
- if self._classes is None:
- self._classes = self.subclasses_of ()
- return SelfDeprecatingDict (dict.fromkeys (self._classes))
- classes = property (_get_classes)
-
- def get (self, moniker):
- try:
- return _wmi_object (self.wmi.Get (moniker))
- except pywintypes.com_error:
- handle_com_error ()
-
- def handle (self):
- """The raw OLE object representing the WMI namespace"""
- return self._namespace
-
- def subclasses_of (self, root="", regex=r".*"):
- try:
- SubclassesOf = self._namespace.SubclassesOf
- except AttributeError:
- return set ()
- else:
- return set (
- c.Path_.Class
- for c in SubclassesOf (root)
- if re.match (regex, c.Path_.Class)
- )
-
- def instances (self, 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 ()
- """
- try:
- return [_wmi_object (obj) for obj in self._namespace.InstancesOf (class_name)]
- except pywintypes.com_error:
- handle_com_error ()
-
- def new (self, wmi_class, **kwargs):
- """This is now implemented by a call to :meth:`_wmi_class.new`"""
- return getattr (self, wmi_class).new (**kwargs)
-
- new_instance_of = new
-
- def _raw_query (self, wql):
- """Execute a WQL query and return its raw results. Use the flags
- recommended by Microsoft to achieve a read-only, semi-synchronous
- query where the time is taken while looping through.
- NB Backslashes need to be doubled up.
- """
- flags = wbemFlagReturnImmediately | wbemFlagForwardOnly
- wql = wql.replace ("\\", "\\\\")
- try:
- return self._namespace.ExecQuery (strQuery=wql, iFlags=flags)
- except pywintypes.com_error:
- handle_com_error ()
-
- def query (self, wql, instance_of=None, fields=[]):
- """Perform an arbitrary query against a WMI object, and return
- a list of _wmi_object representations of the results.
- """
- return [ _wmi_object (obj, instance_of, fields) for obj in self._raw_query(wql) ]
-
- def fetch_as_classes (self, 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.
- """
- wql = "SELECT %s FROM %s" % (fields and ", ".join (fields) or "*", wmi_classname)
- if where_clause:
- wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()])
- return [_wmi_result (obj, fields) for obj in self._raw_query(wql)]
-
- def fetch_as_lists (self, 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.
- """
- wql = "SELECT %s FROM %s" % (", ".join (fields), wmi_classname)
- if where_clause:
- wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()])
- results = []
- for obj in self._raw_query(wql):
- results.append ([obj.Properties_ (field).Value for field in fields])
- return results
-
- def watch_for (
- self,
- 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
- """
- if isinstance (wmi_class, _wmi_class):
- class_name = wmi_class._class_name
- else:
- class_name = wmi_class
- wmi_class = getattr (self, class_name)
- is_extrinsic = "__ExtrinsicEvent" in wmi_class.derivation ()
- if raw_wql:
- wql = raw_wql
- else:
- fields = set (['TargetInstance'] + fields)
- field_list = ", ".join (fields) or "*"
- if is_extrinsic:
- if where_clause:
- where = " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items ()])
- else:
- where = ""
- wql = "SELECT " + field_list + " FROM " + class_name + where
- else:
- if where_clause:
- where = " AND " + " AND ".join (["TargetInstance.%s = '%s'" % (k, v) for k, v in where_clause.items ()])
- else:
- where = ""
- wql = \
- "SELECT %s FROM __Instance%sEvent WITHIN %d WHERE TargetInstance ISA '%s' %s" % \
- (field_list, notification_type, delay_secs, class_name, where)
-
- try:
- return _wmi_watcher (
- self._namespace.ExecNotificationQuery (wql),
- is_extrinsic=is_extrinsic,
- fields=fields
- )
- except pywintypes.com_error:
- handle_com_error ()
-
- def __getattr__ (self, attribute):
- """Offer WMI classes as simple attributes. Pass through any untrapped
- unattribute to the underlying OLE object. This means that new or
- unmapped functionality is still available to the module user.
- """
- #
- # Don't try to match against known classes as was previously
- # done since the list may not have been requested
- # (find_classes=False).
- #
- try:
- return self._cached_classes (attribute)
- except pywintypes.com_error:
- return getattr (self._namespace, attribute)
-
- def _cached_classes (self, class_name):
- """Standard caching helper which keeps track of classes
- already retrieved by name and returns the existing object
- if found. If this is the first retrieval, store it and
- pass it back
- """
- if class_name not in self._classes_map:
- self._classes_map[class_name] = _wmi_class (self, self._namespace.Get (class_name))
- return self._classes_map[class_name]
-
- def _getAttributeNames (self):
- """Return list of classes for IPython completion engine"""
- return [x for x in self.classes if not x.startswith ('__')]
-
-#
-# class _wmi_watcher
-#
-class _wmi_watcher:
- """Helper class for WMI.watch_for below (qv)"""
-
- _event_property_map = {
- "TargetInstance" : _wmi_object,
- "PreviousInstance" : _wmi_object
- }
- def __init__ (self, wmi_event, is_extrinsic, fields=[]):
- self.wmi_event = wmi_event
- self.is_extrinsic = is_extrinsic
- self.fields = fields
-
- def __call__ (self, timeout_ms=-1):
- """When called, return the instance which caused the event. Supports
- timeout in milliseconds (defaulting to infinite). If the watcher
- times out, :exc:`x_wmi_timed_out` is raised. This makes it easy to support
- watching for multiple objects.
- """
- try:
- event = self.wmi_event.NextEvent (timeout_ms)
- if self.is_extrinsic:
- return _wmi_event (event, None, self.fields)
- else:
- return _wmi_event (
- event.Properties_ ("TargetInstance").Value,
- _wmi_object (event, property_map=self._event_property_map),
- self.fields
- )
- except pywintypes.com_error:
- handle_com_error ()
-
-PROTOCOL = "winmgmts:"
-def connect (
- 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.
- """
- global _DEBUG
- _DEBUG = debug
-
- try:
- try:
- if wmi:
- obj = wmi
-
- elif moniker:
- if not moniker.startswith (PROTOCOL):
- moniker = PROTOCOL + moniker
- obj = GetObject (moniker)
-
- else:
- if user:
- if privileges or suffix:
- raise x_wmi_authentication ("You can't specify privileges or a suffix as well as a username")
- elif computer in (None, '', '.'):
- raise x_wmi_authentication ("You can only specify user/password for a remote connection")
- else:
- obj = connect_server (
- server=computer,
- namespace=namespace,
- user=user,
- password=password,
- authority=authority,
- impersonation_level=impersonation_level,
- authentication_level=authentication_level
- )
-
- else:
- moniker = construct_moniker (
- computer=computer,
- impersonation_level=impersonation_level,
- authentication_level=authentication_level,
- authority=authority,
- privileges=privileges,
- namespace=namespace,
- suffix=suffix
- )
- obj = GetObject (moniker)
-
- wmi_type = get_wmi_type (obj)
-
- if wmi_type == "namespace":
- return _wmi_namespace (obj, find_classes)
- elif wmi_type == "class":
- return _wmi_class (None, obj)
- elif wmi_type == "instance":
- return _wmi_object (obj)
- else:
- raise x_wmi ("Unknown moniker type")
-
- except pywintypes.com_error:
- handle_com_error ()
-
- except x_wmi_uninitialised_thread:
- raise x_wmi_uninitialised_thread ("WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex]")
-
-WMI = connect
-
-def construct_moniker (
- computer=None,
- impersonation_level=None,
- authentication_level=None,
- authority=None,
- privileges=None,
- namespace=None,
- suffix=None
-):
- security = []
- if impersonation_level: security.append ("impersonationLevel=%s" % impersonation_level)
- if authentication_level: security.append ("authenticationLevel=%s" % authentication_level)
- #
- # Use of the authority descriptor is invalid on the local machine
- #
- if authority and computer: security.append ("authority=%s" % authority)
- if privileges: security.append ("(%s)" % ", ".join (privileges))
-
- moniker = [PROTOCOL]
- if security: moniker.append ("{%s}!" % ",".join (security))
- if computer: moniker.append ("//%s/" % computer)
- if namespace:
- parts = re.split (r"[/\\]", namespace)
- if parts[0] != 'root':
- parts.insert (0, "root")
- moniker.append ("/".join (parts))
- if suffix: moniker.append (":%s" % suffix)
- return "".join (moniker)
-
-def get_wmi_type (obj):
- try:
- path = obj.Path_
- except AttributeError:
- return "namespace"
- else:
- if path.IsClass:
- return "class"
- else:
- return "instance"
-
-def connect_server (
- server,
- namespace = "",
- user = "",
- password = "",
- locale = "",
- authority = "",
- impersonation_level="",
- authentication_level="",
- security_flags = 0x80,
- named_value_set = None
-):
- """Return a remote server running WMI
-
- :param server: name of the server
- :param namespace: namespace to connect to - defaults to whatever's defined as default
- :param user: username to connect as, either local or domain (dom\\name or user@domain for XP)
- :param password: leave blank to use current context
- :param locale: desired locale in form MS_XXXX (eg MS_409 for Am En)
- :param authority: either "Kerberos:" or an NT domain. Not needed if included in user
- :param impersonation_level: valid WMI impersonation level
- :param security_flags: if 0, connect will wait forever; if 0x80, connect will timeout at 2 mins
- :param 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)
- """
- #
- # Thanks to Matt Mercer for example code to set
- # impersonation & authentication on ConnectServer
- #
- if impersonation_level:
- try:
- impersonation = getattr (obj._constants, "wbemImpersonationLevel%s" % impersonation_level.title ())
- except AttributeError:
- raise x_wmi_authentication ("No such impersonation level: %s" % impersonation_level)
- else:
- impersonation = None
-
- if authentication_level:
- try:
- authentication = getattr (obj._constants, "wbemAuthenticationLevel%s" % authentication_level.title ())
- except AttributeError:
- raise x_wmi_authentication ("No such impersonation level: %s" % impersonation_level)
- else:
- authentication = None
-
- server = Dispatch ("WbemScripting.SWbemLocator").\
- ConnectServer (
- server,
- namespace,
- user,
- password,
- locale,
- authority,
- security_flags,
- named_value_set
- )
- if impersonation:
- server.Security_.ImpersonationLevel = impersonation
- if authentication:
- server.Security_.AuthenticationLevel = authentication
- return server
-
-def Registry (
- computer=None,
- impersonation_level="Impersonate",
- authentication_level="Default",
- authority=None,
- privileges=None,
- moniker=None
-):
-
- warnings.warn ("This function can be implemented using wmi.WMI (namespace='DEFAULT').StdRegProv", DeprecationWarning)
- if not moniker:
- moniker = construct_moniker (
- computer=computer,
- impersonation_level=impersonation_level,
- authentication_level=authentication_level,
- authority=authority,
- privileges=privileges,
- namespace="default",
- suffix="StdRegProv"
- )
-
- try:
- return _wmi_object (GetObject (moniker))
-
- except pywintypes.com_error:
- handle_com_error ()
-
-#
-# Typical use test
-#
-if __name__ == '__main__':
- system = WMI ()
- for my_computer in system.Win32_ComputerSystem ():
- print ("Disks on", my_computer.Name)
- for disk in system.Win32_LogicalDisk ():
- print (disk.Caption, disk.Description, disk.ProviderName or "")
-
+""" +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 :class:`_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. +""" +__VERSION__ = __version__ = "1.4.6" + +_DEBUG = False + +import sys +import datetime +import re +import struct +import warnings + +from win32com.client import GetObject, Dispatch +import pywintypes + +def signed_to_unsigned (signed): + """Convert a (possibly signed) long to unsigned hex. Useful + when converting a COM error code to the more conventional + 8-digit hex:: + + print "%08X" % signed_to_unsigned (-2147023174) + """ + unsigned, = struct.unpack ("L", struct.pack ("l", signed)) + return unsigned + +class SelfDeprecatingDict (object): + """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`. + """ + + dict_only = set (dir (dict)).difference (dir (list)) + + def __init__ (self, dictlike): + self.dict = dict (dictlike) + self.list = list (self.dict) + + def __getattr__ (self, attribute): + if attribute in self.dict_only: + warnings.warn ("In future this will be a list and not a dictionary", DeprecationWarning) + return getattr (self.dict, attribute) + else: + return getattr (self.list, attribute) + + def __iter__ (self): + return iter (self.list) + + def __str__ (self): + return str (self.list) + + def __repr__ (self): + return repr (self.list) + + def __getitem__ (self, item): + try: + return self.list[item] + except TypeError: + return self.dict[item] + +class ProvideConstants (object): + """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 :attr:`_constants` + property. (From Thomas Heller on c.l.py). + """ + def __init__(self, comobj): + comobj.__dict__["_constants"] = self + self.__typecomp = \ + comobj._oleobj_.GetTypeInfo().GetContainingTypeLib()[0].GetTypeComp() + + def __getattr__(self, name): + if name.startswith("__") and name.endswith("__"): + raise AttributeError (name) + result = self.__typecomp.Bind(name) + if not result[0]: + raise AttributeError (name) + return result[1].value + +obj = GetObject ("winmgmts:") +ProvideConstants (obj) + +wbemErrInvalidQuery = obj._constants.wbemErrInvalidQuery +wbemErrTimedout = obj._constants.wbemErrTimedout +wbemFlagReturnImmediately = obj._constants.wbemFlagReturnImmediately +wbemFlagForwardOnly = obj._constants.wbemFlagForwardOnly + +# +# Exceptions +# +class x_wmi (Exception): + """Ancestor of all wmi-related exceptions. Keeps track of + an info message and the underlying COM error if any, exposed + as the :attr:`com_error` attribute. + """ + def __init__ (self, info="", com_error=None): + self.info = info + self.com_error = com_error + + def __str__ (self): + return "<x_wmi: %s %s>" % ( + self.info or "Unexpected COM Error", + self.com_error or "(no underlying exception)" + ) + +class x_wmi_invalid_query (x_wmi): + "Raised when a WMI returns `wbemErrInvalidQuery`" + pass + +class x_wmi_timed_out (x_wmi): + "Raised when a watcher times out" + pass + +class x_wmi_no_namespace (x_wmi): + """Raised when an attempt is made to query or watch + from a class without a namespace. + """ + pass + +class x_access_denied (x_wmi): + "Raised when WMI raises 80070005" + pass + +class x_wmi_authentication (x_wmi): + "Raised when an invalid combination of authentication properties is attempted when connecting" + pass + +class x_wmi_uninitialised_thread (x_wmi): + """Raised when WMI returns 800401E4 on connection, usually + indicating that no COM threading model has been initialised + """ + pass + +WMI_EXCEPTIONS = { + signed_to_unsigned (wbemErrInvalidQuery) : x_wmi_invalid_query, + signed_to_unsigned (wbemErrTimedout) : x_wmi_timed_out, + 0x80070005 : x_access_denied, + 0x80041003 : x_access_denied, + 0x800401E4 : x_wmi_uninitialised_thread, +} + +def handle_com_error (err=None): + """Convenience wrapper for displaying all manner of COM errors. + Raises a :exc:`x_wmi` exception with more useful information attached + + :param err: The structure attached to a `pywintypes.com_error` + """ + if err is None: + _, err, _ = sys.exc_info () + hresult_code, hresult_name, additional_info, parameter_in_error = err.args + hresult_code = signed_to_unsigned (hresult_code) + exception_string = ["%s - %s" % (hex (hresult_code), hresult_name)] + scode = None + if additional_info: + wcode, source_of_error, error_description, whlp_file, whlp_context, scode = additional_info + scode = signed_to_unsigned (scode) + exception_string.append (" Error in: %s" % source_of_error) + exception_string.append (" %s - %s" % (hex (scode), (error_description or "").strip ())) + for error_code, klass in WMI_EXCEPTIONS.items (): + if error_code in (hresult_code, scode): + break + else: + klass = x_wmi + raise klass (com_error=err) + + +BASE = datetime.datetime (1601, 1, 1) +def from_1601 (ns100): + return BASE + datetime.timedelta (microseconds=int (ns100) / 10) + +def 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. + + :param year: The year element of the date/time + :param month: The month element of the date/time + :param day: The day element of the date/time + :param hours: The hours element of the date/time + :param minutes: The minutes element of the date/time + :param seconds: The seconds element of the date/time + :param microseconds: The microseconds element of the date/time + :param timezone: The timeezone element of the date/time + + :returns: A WMI datetime string of the form: `yyyymmddHHMMSS.mmmmmm+UUU` + """ + def str_or_stars (i, length): + if i is None: + return "*" * length + else: + return str (i).rjust (length, "0") + + wmi_time = "" + wmi_time += str_or_stars (year, 4) + wmi_time += str_or_stars (month, 2) + wmi_time += str_or_stars (day, 2) + wmi_time += str_or_stars (hours, 2) + wmi_time += str_or_stars (minutes, 2) + wmi_time += str_or_stars (seconds, 2) + wmi_time += "." + wmi_time += str_or_stars (microseconds, 6) + wmi_time += "+" + wmi_time += str_or_stars (timezone, 3) + + return wmi_time + +def 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. + + :param wmi_time: The WMI datetime string in `yyyymmddHHMMSS.mmmmmm+UUU` format + + :returns: A 9-tuple of (year, month, day, hours, minutes, seconds, microseconds, timezone) + """ + def int_or_none (s, start, end): + try: + return int (s[start:end]) + except ValueError: + return None + + year = int_or_none (wmi_time, 0, 4) + month = int_or_none (wmi_time, 4, 6) + day = int_or_none (wmi_time, 6, 8) + hours = int_or_none (wmi_time, 8, 10) + minutes = int_or_none (wmi_time, 10, 12) + seconds = int_or_none (wmi_time, 12, 14) + microseconds = int_or_none (wmi_time, 15, 21) + timezone = wmi_time[22:] + if timezone == "***": + timezone = None + + return year, month, day, hours, minutes, seconds, microseconds, timezone + +def _set (obj, attribute, value): + """Helper function to add an attribute directly into the instance + dictionary, bypassing possible `__getattr__` calls + + :param obj: Any python object + :param attribute: String containing attribute name + :param value: Any python object + """ + obj.__dict__[attribute] = value + +class _wmi_method: + """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. + """ + + def __init__ (self, ole_object, method_name): + """ + :param ole_object: The WMI class/instance whose method is to be called + :param method_name: The name of the method to be called + """ + try: + self.ole_object = Dispatch (ole_object) + self.method = ole_object.Methods_ (method_name) + self.qualifiers = {} + for q in self.method.Qualifiers_: + self.qualifiers[q.Name] = q.Value + self.provenance = "\n".join (self.qualifiers.get ("MappingStrings", [])) + + self.in_parameters = self.method.InParameters + self.out_parameters = self.method.OutParameters + if self.in_parameters is None: + self.in_parameter_names = [] + else: + self.in_parameter_names = [(i.Name, i.IsArray) for i in self.in_parameters.Properties_] + if self.out_parameters is None: + self.out_parameter_names = [] + else: + self.out_parameter_names = [(i.Name, i.IsArray) for i in self.out_parameters.Properties_] + + doc = "%s (%s) => (%s)" % ( + method_name, + ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.in_parameter_names]), + ", ".join ([name + ("", "[]")[is_array] for (name, is_array) in self.out_parameter_names]) + ) + privileges = self.qualifiers.get ("Privileges", []) + if privileges: + doc += " | Needs: " + ", ".join (privileges) + self.__doc__ = doc + except pywintypes.com_error: + handle_com_error () + + def __call__ (self, *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. + """ + try: + if self.in_parameters: + parameter_names = {} + for name, is_array in self.in_parameter_names: + parameter_names[name] = is_array + + parameters = self.in_parameters + + # + # Check positional parameters first + # + for n_arg in range (len (args)): + arg = args[n_arg] + parameter = parameters.Properties_[n_arg] + if parameter.IsArray: + try: list (arg) + except TypeError: raise TypeError ("parameter %d must be iterable" % n_arg) + parameter.Value = arg + + # + # If any keyword param supersedes a positional one, + # it'll simply overwrite it. + # + for k, v in kwargs.items (): + is_array = parameter_names.get (k) + if is_array is None: + raise AttributeError ("%s is not a valid parameter for %s" % (k, self.__doc__)) + else: + if is_array: + try: list (v) + except TypeError: raise TypeError ("%s must be iterable" % k) + parameters.Properties_ (k).Value = v + + result = self.ole_object.ExecMethod_ (self.method.Name, self.in_parameters) + else: + result = self.ole_object.ExecMethod_ (self.method.Name) + + results = [] + for name, is_array in self.out_parameter_names: + value = result.Properties_ (name).Value + if is_array: + # + # Thanks to Jonas Bjering for bug report and patch + # + results.append (list (value or [])) + else: + results.append (value) + return tuple (results) + + except pywintypes.com_error: + handle_com_error () + + def __repr__ (self): + return "<function %s>" % self.__doc__ + +class _wmi_property (object): + + def __init__ (self, property): + self.property = property + self.name = property.Name + self.value = property.Value + self.qualifiers = dict ((q.Name, q.Value) for q in property.Qualifiers_) + self.type = self.qualifiers.get ("CIMTYPE", None) + + def set (self, value): + self.property.Value = value + + def __getattr__ (self, attr): + return getattr (self.property, attr) + +# +# class _wmi_object +# +class _wmi_object: + """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 :class:`_wmi_class` + on the parent :class:`_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 + """ + + def __init__ (self, ole_object, instance_of=None, fields=[], property_map={}): + try: + _set (self, "ole_object", ole_object) + _set (self, "id", ole_object.Path_.DisplayName.lower ()) + _set (self, "_instance_of", instance_of) + _set (self, "properties", {}) + _set (self, "methods", {}) + _set (self, "property_map", property_map) + _set (self, "_associated_classes", None) + _set (self, "_keys", None) + + if fields: + for field in fields: + self.properties[field] = None + else: + for p in ole_object.Properties_: + self.properties[p.Name] = None + + for m in ole_object.Methods_: + self.methods[m.Name] = None + + _set (self, "_properties", self.properties.keys ()) + _set (self, "_methods", self.methods.keys ()) + _set (self, "qualifiers", dict ((q.Name, q.Value) for q in self.ole_object.Qualifiers_)) + + except pywintypes.com_error: + handle_com_error () + + def __lt__ (self, other): + return self.id < other.id + + def __str__ (self): + """For a call to print [object] return the OLE description + of the properties / values of the object + """ + try: + return self.ole_object.GetObjectText_ () + except pywintypes.com_error: + handle_com_error () + + def __repr__ (self): + """ + Indicate both the fact that this is a wrapped WMI object + and the WMI object's own identifying class. + """ + try: + return "<%s: %s>" % (self.__class__.__name__, str (self.Path_.Path)) + except pywintypes.com_error: + handle_com_error () + + def _cached_properties (self, attribute): + if self.properties[attribute] is None: + self.properties[attribute] = _wmi_property (self.ole_object.Properties_ (attribute)) + return self.properties[attribute] + + def _cached_methods (self, attribute): + if self.methods[attribute] is None: + self.methods[attribute] = _wmi_method (self.ole_object, attribute) + return self.methods[attribute] + + def __getattr__ (self, attribute): + """ + Attempt to pass attribute calls to the proxied COM object. + If the attribute is recognised as a property, return its value; + if it is recognised as a method, return a method wrapper which + can then be called with parameters; otherwise pass the lookup + on to the underlying object. + """ + try: + if attribute in self.properties: + property = self._cached_properties (attribute) + factory = self.property_map.get (attribute, self.property_map.get (property.type, lambda x: x)) + value = factory (property.value) + # + # If this is an association, certain of its properties + # are actually the paths to the aspects of the association, + # so translate them automatically into WMI objects. + # + if property.type.startswith ("ref:"): + return WMI (moniker=value) + else: + return value + elif attribute in self.methods: + return self._cached_methods (attribute) + else: + return getattr (self.ole_object, attribute) + except pywintypes.com_error: + handle_com_error () + + def __setattr__ (self, attribute, value): + """If the attribute to be set is valid for the proxied + COM object, set that objects's parameter value; if not, + raise an exception. + """ + try: + if attribute in self.properties: + self._cached_properties (attribute).set (value) + if self.ole_object.Path_.Path: + self.ole_object.Put_ () + else: + raise AttributeError (attribute) + except pywintypes.com_error: + handle_com_error () + + def __eq__ (self, other): + return self.id == other.id + + def __hash__ (self): + return hash (self.id) + + def _getAttributeNames (self): + """Return list of methods/properties for IPython completion""" + attribs = [str (x) for x in self.methods.keys ()] + attribs.extend ([str (x) for x in self.properties.keys ()]) + return attribs + + def _get_keys (self): + """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 + """ + # NB You can get the keys of an instance more directly, via + # Path\_.Keys but this doesn't apply to classes. The technique + # here appears to work for both. + if self._keys is None: + _set (self, "_keys", []) + for property in self.ole_object.Properties_: + for qualifier in property.Qualifiers_: + if qualifier.Name == "key" and qualifier.Value: + self._keys.append (property.Name) + return self._keys + keys = property (_get_keys) + + def put (self): + """Push all outstanding property updates back to the + WMI database. + """ + self.ole_object.Put_ () + + def set (self, **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. + """ + if kwargs: + try: + for attribute, value in kwargs.items (): + if attribute in self.properties: + self._cached_properties (attribute).set (value) + else: + raise AttributeError (attribute) + # + # Only try to write the attributes + # back if the object exists. + # + if self.ole_object.Path_.Path: + self.ole_object.Put_ () + except pywintypes.com_error: + handle_com_error () + + def path (self): + """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 + + .. Do more with this + """ + try: + return self.ole_object.Path_ + except pywintypes.com_error: + handle_com_error () + + def derivation (self): + """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 ()) + """ + try: + return self.ole_object.Derivation_ + except pywintypes.com_error: + handle_com_error () + + def _cached_associated_classes (self): + if self._associated_classes is None: + if isinstance (self, _wmi_class): + params = {'bSchemaOnly' : True} + else: + params = {'bClassesOnly' : True} + try: + associated_classes = dict ( + (assoc.Path_.Class, _wmi_class (self._namespace, assoc)) for + assoc in self.ole_object.Associators_ (**params) + ) + _set (self, "_associated_classes", associated_classes) + except pywintypes.com_error: + handle_com_error () + + return self._associated_classes + associated_classes = property (_cached_associated_classes) + + def associators (self, 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 + """ + try: + return [ + _wmi_object (i) for i in \ + self.ole_object.Associators_ ( + strAssocClass=wmi_association_class, + strResultClass=wmi_result_class + ) + ] + except pywintypes.com_error: + handle_com_error () + + def references (self, 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 + """ + # + # FIXME: Allow an actual class to be passed in, using + # its .Path_.RelPath property to determine the string + # + try: + return [_wmi_object (i) for i in self.ole_object.References_ (strResultClass=wmi_class)] + except pywintypes.com_error: + handle_com_error () + +# +# class _wmi_event +# +class _wmi_event (_wmi_object): + """Slight extension of the _wmi_object class to allow + objects which are the result of events firing to return + extra information such as the type of event. + """ + event_type_re = re.compile ("__Instance(Creation|Modification|Deletion)Event") + def __init__ (self, event, event_info, fields=[]): + _wmi_object.__init__ (self, event, fields=fields) + _set (self, "event_type", None) + _set (self, "timestamp", None) + _set (self, "previous", None) + + if event_info: + event_type = self.event_type_re.match (event_info.Path_.Class).group (1).lower () + _set (self, "event_type", event_type) + if hasattr (event_info, "TIME_CREATED"): + _set (self, "timestamp", from_1601 (event_info.TIME_CREATED)) + if hasattr (event_info, "PreviousInstance"): + _set (self, "previous", event_info.PreviousInstance) + +# +# class _wmi_class +# +class _wmi_class (_wmi_object): + """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:') + """ + def __init__ (self, namespace, wmi_class): + _wmi_object.__init__ (self, wmi_class) + _set (self, "_class_name", wmi_class.Path_.Class) + if namespace: + _set (self, "_namespace", namespace) + else: + class_moniker = wmi_class.Path_.DisplayName + winmgmts, namespace_moniker, class_name = class_moniker.split (":") + namespace = _wmi_namespace (GetObject (winmgmts + ":" + namespace_moniker), False) + _set (self, "_namespace", namespace) + + def query (self, 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. + """ + # + # FIXME: Not clear if this can ever happen + # + if self._namespace is None: + raise x_wmi_no_namespace ("You cannot query directly from a WMI class") + + try: + field_list = ", ".join (fields) or "*" + wql = "SELECT " + field_list + " FROM " + self._class_name + if where_clause: + wql += " WHERE " + " AND ". join (["%s = '%s'" % (k, v) for k, v in where_clause.items ()]) + return self._namespace.query (wql, self, fields) + except pywintypes.com_error: + handle_com_error () + + __call__ = query + + def watch_for ( + self, + notification_type="operation", + delay_secs=1, + fields=[], + **where_clause + ): + if self._namespace is None: + raise x_wmi_no_namespace ("You cannot watch directly from a WMI class") + + valid_notification_types = ("operation", "creation", "deletion", "modification") + if notification_type.lower () not in valid_notification_types: + raise x_wmi ("notification_type must be one of %s" % ", ".join (valid_notification_types)) + + return self._namespace.watch_for ( + notification_type=notification_type, + wmi_class=self, + delay_secs=delay_secs, + fields=fields, + **where_clause + ) + + def instances (self): + """Return a list of instances of the WMI class + """ + try: + return [_wmi_object (instance, self) for instance in self.Instances_ ()] + except pywintypes.com_error: + handle_com_error () + + def new (self, **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. + """ + try: + obj = _wmi_object (self.SpawnInstance_ (), self) + obj.set (**kwargs) + return obj + except pywintypes.com_error: + handle_com_error () + +# +# class _wmi_result +# +class _wmi_result: + """Simple, data only result for targeted WMI queries which request + data only result classes via fetch_as_classes. + """ + def __init__(self, obj, attributes): + if attributes: + for attr in attributes: + self.__dict__[attr] = obj.Properties_ (attr).Value + else: + for p in obj.Properties_: + attr = p.Name + self.__dict__[attr] = obj.Properties_(attr).Value + +# +# class WMI +# +class _wmi_namespace: + """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 + """ + def __init__ (self, namespace, find_classes): + _set (self, "_namespace", namespace) + # + # wmi attribute preserved for backwards compatibility + # + _set (self, "wmi", namespace) + + self._classes = None + self._classes_map = {} + # + # Pick up the list of classes under this namespace + # so that they can be queried, and used as though + # properties of the namespace by means of the __getattr__ + # hook below. + # If the namespace does not support SubclassesOf, carry on + # regardless + # + if find_classes: + _ = self.classes + + def __repr__ (self): + return "<_wmi_namespace: %s>" % self.wmi + + def __str__ (self): + return repr (self) + + def _get_classes (self): + if self._classes is None: + self._classes = self.subclasses_of () + return SelfDeprecatingDict (dict.fromkeys (self._classes)) + classes = property (_get_classes) + + def get (self, moniker): + try: + return _wmi_object (self.wmi.Get (moniker)) + except pywintypes.com_error: + handle_com_error () + + def handle (self): + """The raw OLE object representing the WMI namespace""" + return self._namespace + + def subclasses_of (self, root="", regex=r".*"): + try: + SubclassesOf = self._namespace.SubclassesOf + except AttributeError: + return set () + else: + return set ( + c.Path_.Class + for c in SubclassesOf (root) + if re.match (regex, c.Path_.Class) + ) + + def instances (self, 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 () + """ + try: + return [_wmi_object (obj) for obj in self._namespace.InstancesOf (class_name)] + except pywintypes.com_error: + handle_com_error () + + def new (self, wmi_class, **kwargs): + """This is now implemented by a call to :meth:`_wmi_class.new`""" + return getattr (self, wmi_class).new (**kwargs) + + new_instance_of = new + + def _raw_query (self, wql): + """Execute a WQL query and return its raw results. Use the flags + recommended by Microsoft to achieve a read-only, semi-synchronous + query where the time is taken while looping through. + NB Backslashes need to be doubled up. + """ + flags = wbemFlagReturnImmediately | wbemFlagForwardOnly + wql = wql.replace ("\\", "\\\\") + try: + return self._namespace.ExecQuery (strQuery=wql, iFlags=flags) + except pywintypes.com_error: + handle_com_error () + + def query (self, wql, instance_of=None, fields=[]): + """Perform an arbitrary query against a WMI object, and return + a list of _wmi_object representations of the results. + """ + return [ _wmi_object (obj, instance_of, fields) for obj in self._raw_query(wql) ] + + def fetch_as_classes (self, 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. + """ + wql = "SELECT %s FROM %s" % (fields and ", ".join (fields) or "*", wmi_classname) + if where_clause: + wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()]) + return [_wmi_result (obj, fields) for obj in self._raw_query(wql)] + + def fetch_as_lists (self, 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. + """ + wql = "SELECT %s FROM %s" % (", ".join (fields), wmi_classname) + if where_clause: + wql += " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items()]) + results = [] + for obj in self._raw_query(wql): + results.append ([obj.Properties_ (field).Value for field in fields]) + return results + + def watch_for ( + self, + 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 + """ + if isinstance (wmi_class, _wmi_class): + class_name = wmi_class._class_name + else: + class_name = wmi_class + wmi_class = getattr (self, class_name) + is_extrinsic = "__ExtrinsicEvent" in wmi_class.derivation () + if raw_wql: + wql = raw_wql + else: + fields = set (['TargetInstance'] + fields) + field_list = ", ".join (fields) or "*" + if is_extrinsic: + if where_clause: + where = " WHERE " + " AND ".join (["%s = '%s'" % (k, v) for k, v in where_clause.items ()]) + else: + where = "" + wql = "SELECT " + field_list + " FROM " + class_name + where + else: + if where_clause: + where = " AND " + " AND ".join (["TargetInstance.%s = '%s'" % (k, v) for k, v in where_clause.items ()]) + else: + where = "" + wql = \ + "SELECT %s FROM __Instance%sEvent WITHIN %d WHERE TargetInstance ISA '%s' %s" % \ + (field_list, notification_type, delay_secs, class_name, where) + + try: + return _wmi_watcher ( + self._namespace.ExecNotificationQuery (wql), + is_extrinsic=is_extrinsic, + fields=fields + ) + except pywintypes.com_error: + handle_com_error () + + def __getattr__ (self, attribute): + """Offer WMI classes as simple attributes. Pass through any untrapped + unattribute to the underlying OLE object. This means that new or + unmapped functionality is still available to the module user. + """ + # + # Don't try to match against known classes as was previously + # done since the list may not have been requested + # (find_classes=False). + # + try: + return self._cached_classes (attribute) + except pywintypes.com_error: + return getattr (self._namespace, attribute) + + def _cached_classes (self, class_name): + """Standard caching helper which keeps track of classes + already retrieved by name and returns the existing object + if found. If this is the first retrieval, store it and + pass it back + """ + if class_name not in self._classes_map: + self._classes_map[class_name] = _wmi_class (self, self._namespace.Get (class_name)) + return self._classes_map[class_name] + + def _getAttributeNames (self): + """Return list of classes for IPython completion engine""" + return [x for x in self.classes if not x.startswith ('__')] + +# +# class _wmi_watcher +# +class _wmi_watcher: + """Helper class for WMI.watch_for below (qv)""" + + _event_property_map = { + "TargetInstance" : _wmi_object, + "PreviousInstance" : _wmi_object + } + def __init__ (self, wmi_event, is_extrinsic, fields=[]): + self.wmi_event = wmi_event + self.is_extrinsic = is_extrinsic + self.fields = fields + + def __call__ (self, timeout_ms=-1): + """When called, return the instance which caused the event. Supports + timeout in milliseconds (defaulting to infinite). If the watcher + times out, :exc:`x_wmi_timed_out` is raised. This makes it easy to support + watching for multiple objects. + """ + try: + event = self.wmi_event.NextEvent (timeout_ms) + if self.is_extrinsic: + return _wmi_event (event, None, self.fields) + else: + return _wmi_event ( + event.Properties_ ("TargetInstance").Value, + _wmi_object (event, property_map=self._event_property_map), + self.fields + ) + except pywintypes.com_error: + handle_com_error () + +PROTOCOL = "winmgmts:" +def connect ( + 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. + """ + global _DEBUG + _DEBUG = debug + + try: + try: + if wmi: + obj = wmi + + elif moniker: + if not moniker.startswith (PROTOCOL): + moniker = PROTOCOL + moniker + obj = GetObject (moniker) + + else: + if user: + if privileges or suffix: + raise x_wmi_authentication ("You can't specify privileges or a suffix as well as a username") + elif computer in (None, '', '.'): + raise x_wmi_authentication ("You can only specify user/password for a remote connection") + else: + obj = connect_server ( + server=computer, + namespace=namespace, + user=user, + password=password, + authority=authority, + impersonation_level=impersonation_level, + authentication_level=authentication_level + ) + + else: + moniker = construct_moniker ( + computer=computer, + impersonation_level=impersonation_level, + authentication_level=authentication_level, + authority=authority, + privileges=privileges, + namespace=namespace, + suffix=suffix + ) + obj = GetObject (moniker) + + wmi_type = get_wmi_type (obj) + + if wmi_type == "namespace": + return _wmi_namespace (obj, find_classes) + elif wmi_type == "class": + return _wmi_class (None, obj) + elif wmi_type == "instance": + return _wmi_object (obj) + else: + raise x_wmi ("Unknown moniker type") + + except pywintypes.com_error: + handle_com_error () + + except x_wmi_uninitialised_thread: + raise x_wmi_uninitialised_thread ("WMI returned a syntax error: you're probably running inside a thread without first calling pythoncom.CoInitialize[Ex]") + +WMI = connect + +def construct_moniker ( + computer=None, + impersonation_level=None, + authentication_level=None, + authority=None, + privileges=None, + namespace=None, + suffix=None +): + security = [] + if impersonation_level: security.append ("impersonationLevel=%s" % impersonation_level) + if authentication_level: security.append ("authenticationLevel=%s" % authentication_level) + # + # Use of the authority descriptor is invalid on the local machine + # + if authority and computer: security.append ("authority=%s" % authority) + if privileges: security.append ("(%s)" % ", ".join (privileges)) + + moniker = [PROTOCOL] + if security: moniker.append ("{%s}!" % ",".join (security)) + if computer: moniker.append ("//%s/" % computer) + if namespace: + parts = re.split (r"[/\\]", namespace) + if parts[0] != 'root': + parts.insert (0, "root") + moniker.append ("/".join (parts)) + if suffix: moniker.append (":%s" % suffix) + return "".join (moniker) + +def get_wmi_type (obj): + try: + path = obj.Path_ + except AttributeError: + return "namespace" + else: + if path.IsClass: + return "class" + else: + return "instance" + +def connect_server ( + server, + namespace = "", + user = "", + password = "", + locale = "", + authority = "", + impersonation_level="", + authentication_level="", + security_flags = 0x80, + named_value_set = None +): + """Return a remote server running WMI + + :param server: name of the server + :param namespace: namespace to connect to - defaults to whatever's defined as default + :param user: username to connect as, either local or domain (dom\\name or user@domain for XP) + :param password: leave blank to use current context + :param locale: desired locale in form MS_XXXX (eg MS_409 for Am En) + :param authority: either "Kerberos:" or an NT domain. Not needed if included in user + :param impersonation_level: valid WMI impersonation level + :param security_flags: if 0, connect will wait forever; if 0x80, connect will timeout at 2 mins + :param 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) + """ + # + # Thanks to Matt Mercer for example code to set + # impersonation & authentication on ConnectServer + # + if impersonation_level: + try: + impersonation = getattr (obj._constants, "wbemImpersonationLevel%s" % impersonation_level.title ()) + except AttributeError: + raise x_wmi_authentication ("No such impersonation level: %s" % impersonation_level) + else: + impersonation = None + + if authentication_level: + try: + authentication = getattr (obj._constants, "wbemAuthenticationLevel%s" % authentication_level.title ()) + except AttributeError: + raise x_wmi_authentication ("No such impersonation level: %s" % impersonation_level) + else: + authentication = None + + server = Dispatch ("WbemScripting.SWbemLocator").\ + ConnectServer ( + server, + namespace, + user, + password, + locale, + authority, + security_flags, + named_value_set + ) + if impersonation: + server.Security_.ImpersonationLevel = impersonation + if authentication: + server.Security_.AuthenticationLevel = authentication + return server + +def Registry ( + computer=None, + impersonation_level="Impersonate", + authentication_level="Default", + authority=None, + privileges=None, + moniker=None +): + + warnings.warn ("This function can be implemented using wmi.WMI (namespace='DEFAULT').StdRegProv", DeprecationWarning) + if not moniker: + moniker = construct_moniker ( + computer=computer, + impersonation_level=impersonation_level, + authentication_level=authentication_level, + authority=authority, + privileges=privileges, + namespace="default", + suffix="StdRegProv" + ) + + try: + return _wmi_object (GetObject (moniker)) + + except pywintypes.com_error: + handle_com_error () + +# +# Typical use test +# +if __name__ == '__main__': + system = WMI () + for my_computer in system.Win32_ComputerSystem (): + print ("Disks on", my_computer.Name) + for disk in system.Win32_LogicalDisk (): + print (disk.Caption, disk.Description, disk.ProviderName or "") + diff --git a/test/_bsd.py b/test/_bsd.py index 6f6c8a79..80d8d7da 100644 --- a/test/_bsd.py +++ b/test/_bsd.py @@ -1,141 +1,141 @@ -#!/usr/bin/env python
-#
-# $Id$
-#
-
-import unittest
-import subprocess
-import time
-import re
-import sys
-
-import psutil
-
-from test_psutil import reap_children, PYTHON, DEVNULL
-from _posix import ps
-
-
-def sysctl(cmdline):
- """Expects a sysctl command with an argument and parse the result
- returning only the value of interest.
- """
- p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE)
- result = p.communicate()[0].strip().split()[1]
- if sys.version_info >= (3,):
- result = str(result, sys.stdout.encoding)
- try:
- return int(result)
- except ValueError:
- return result
-
-def parse_sysctl_vmtotal(output):
- """Parse sysctl vm.vmtotal output returning total and free memory
- values.
- """
- line = output.split('\n')[4] # our line of interest
- mobj = re.match(r'Virtual\s+Memory.*Total:\s+(\d+)K,\s+Active\s+(\d+)K.*', line)
- total, active = mobj.groups()
- # values are represented in kilo bytes
- total = int(total) * 1024
- active = int(active) * 1024
- free = total - active
- return total, free
-
-
-class BSDSpecificTestCase(unittest.TestCase):
-
- def setUp(self):
- self.pid = subprocess.Popen(PYTHON, stdout=DEVNULL, stderr=DEVNULL).pid
-
- def tearDown(self):
- reap_children()
-
- def test_TOTAL_PHYMEM(self):
- sysctl_hwphymem = sysctl('sysctl hw.physmem')
- self.assertEqual(sysctl_hwphymem, psutil.TOTAL_PHYMEM)
-
- def test_avail_phymem(self):
- # This test is not particularly accurate and may fail if the OS is
- # consuming memory for other applications.
- # We just want to test that the difference between psutil result
- # and sysctl's is not too high.
- _sum = sum((sysctl("sysctl vm.stats.vm.v_inactive_count"),
- sysctl("sysctl vm.stats.vm.v_cache_count"),
- sysctl("sysctl vm.stats.vm.v_free_count")
- ))
- _pagesize = sysctl("sysctl hw.pagesize")
- sysctl_avail_phymem = _sum * _pagesize
- psutil_avail_phymem = psutil.avail_phymem()
- difference = abs(psutil_avail_phymem - sysctl_avail_phymem)
- # On my system both sysctl and psutil report the same values.
- # Let's use a tollerance of 0.5 MB and consider the test as failed
- # if we go over it.
- if difference > (0.5 * 2**20):
- self.fail("sysctl=%s; psutil=%s; difference=%s;" %(
- sysctl_avail_phymem, psutil_avail_phymem, difference))
-
- def test_total_virtmem(self):
- # This test is not particularly accurate and may fail if the OS is
- # consuming memory for other applications.
- # We just want to test that the difference between psutil result
- # and sysctl's is not too high.
- p = subprocess.Popen("sysctl vm.vmtotal", shell=1, stdout=subprocess.PIPE)
- result = p.communicate()[0].strip()
- if sys.version_info >= (3,):
- result = str(result, sys.stdout.encoding)
- sysctl_total_virtmem, _ = parse_sysctl_vmtotal(result)
- psutil_total_virtmem = psutil.total_virtmem()
- difference = abs(sysctl_total_virtmem - psutil_total_virtmem)
-
- # On my system I get a difference of 4657152 bytes, probably because
- # the system is consuming memory for this same test.
- # Assuming psutil is right, let's use a tollerance of 10 MB and consider
- # the test as failed if we go over it.
- if difference > (10 * 2**20):
- self.fail("sysctl=%s; psutil=%s; difference=%s;" %(
- sysctl_total_virtmem, psutil_total_virtmem, difference)
- )
-
- def test_avail_virtmem(self):
- # This test is not particularly accurate and may fail if the OS is
- # consuming memory for other applications.
- # We just want to test that the difference between psutil result
- # and sysctl's is not too high.
- p = subprocess.Popen("sysctl vm.vmtotal", shell=1, stdout=subprocess.PIPE)
- result = p.communicate()[0].strip()
- if sys.version_info >= (3,):
- result = str(result, sys.stdout.encoding)
- _, sysctl_avail_virtmem = parse_sysctl_vmtotal(result)
- psutil_avail_virtmem = psutil.avail_virtmem()
- difference = abs(sysctl_avail_virtmem - psutil_avail_virtmem)
- # let's assume the test is failed if difference is > 0.5 MB
- if difference > (0.5 * 2**20):
- self.fail("sysctl=%s; psutil=%s; difference=%s;" %(
- sysctl_avail_virtmem, psutil_avail_virtmem, difference))
-
- def test_cached_mem(self):
- sysctl_mem = sysctl("sysctl vm.stats.vm.v_cache_count")
- psutil_mem = psutil.cached_mem()
- self.assertEqual(sysctl_mem, psutil_mem)
-
- def test_process_create_time(self):
- cmdline = "ps -o lstart -p %s" %self.pid
- p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE)
- output = p.communicate()[0]
- if sys.version_info >= (3,):
- output = str(output, sys.stdout.encoding)
- start_ps = output.replace('STARTED', '').strip()
- start_psutil = psutil.Process(self.pid).create_time
- start_psutil = time.strftime("%a %b %e %H:%M:%S %Y",
- time.localtime(start_psutil))
- self.assertEqual(start_ps, start_psutil)
-
-
-if __name__ == '__main__':
- test_suite = unittest.TestSuite()
- test_suite.addTest(unittest.makeSuite(BSDSpecificTestCase))
- unittest.TextTestRunner(verbosity=2).run(test_suite)
-
-
-
-
+#!/usr/bin/env python +# +# $Id$ +# + +import unittest +import subprocess +import time +import re +import sys + +import psutil + +from test_psutil import reap_children, PYTHON, DEVNULL +from _posix import ps + + +def sysctl(cmdline): + """Expects a sysctl command with an argument and parse the result + returning only the value of interest. + """ + p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE) + result = p.communicate()[0].strip().split()[1] + if sys.version_info >= (3,): + result = str(result, sys.stdout.encoding) + try: + return int(result) + except ValueError: + return result + +def parse_sysctl_vmtotal(output): + """Parse sysctl vm.vmtotal output returning total and free memory + values. + """ + line = output.split('\n')[4] # our line of interest + mobj = re.match(r'Virtual\s+Memory.*Total:\s+(\d+)K,\s+Active\s+(\d+)K.*', line) + total, active = mobj.groups() + # values are represented in kilo bytes + total = int(total) * 1024 + active = int(active) * 1024 + free = total - active + return total, free + + +class BSDSpecificTestCase(unittest.TestCase): + + def setUp(self): + self.pid = subprocess.Popen(PYTHON, stdout=DEVNULL, stderr=DEVNULL).pid + + def tearDown(self): + reap_children() + + def test_TOTAL_PHYMEM(self): + sysctl_hwphymem = sysctl('sysctl hw.physmem') + self.assertEqual(sysctl_hwphymem, psutil.TOTAL_PHYMEM) + + def test_avail_phymem(self): + # This test is not particularly accurate and may fail if the OS is + # consuming memory for other applications. + # We just want to test that the difference between psutil result + # and sysctl's is not too high. + _sum = sum((sysctl("sysctl vm.stats.vm.v_inactive_count"), + sysctl("sysctl vm.stats.vm.v_cache_count"), + sysctl("sysctl vm.stats.vm.v_free_count") + )) + _pagesize = sysctl("sysctl hw.pagesize") + sysctl_avail_phymem = _sum * _pagesize + psutil_avail_phymem = psutil.avail_phymem() + difference = abs(psutil_avail_phymem - sysctl_avail_phymem) + # On my system both sysctl and psutil report the same values. + # Let's use a tollerance of 0.5 MB and consider the test as failed + # if we go over it. + if difference > (0.5 * 2**20): + self.fail("sysctl=%s; psutil=%s; difference=%s;" %( + sysctl_avail_phymem, psutil_avail_phymem, difference)) + + def test_total_virtmem(self): + # This test is not particularly accurate and may fail if the OS is + # consuming memory for other applications. + # We just want to test that the difference between psutil result + # and sysctl's is not too high. + p = subprocess.Popen("sysctl vm.vmtotal", shell=1, stdout=subprocess.PIPE) + result = p.communicate()[0].strip() + if sys.version_info >= (3,): + result = str(result, sys.stdout.encoding) + sysctl_total_virtmem, _ = parse_sysctl_vmtotal(result) + psutil_total_virtmem = psutil.total_virtmem() + difference = abs(sysctl_total_virtmem - psutil_total_virtmem) + + # On my system I get a difference of 4657152 bytes, probably because + # the system is consuming memory for this same test. + # Assuming psutil is right, let's use a tollerance of 10 MB and consider + # the test as failed if we go over it. + if difference > (10 * 2**20): + self.fail("sysctl=%s; psutil=%s; difference=%s;" %( + sysctl_total_virtmem, psutil_total_virtmem, difference) + ) + + def test_avail_virtmem(self): + # This test is not particularly accurate and may fail if the OS is + # consuming memory for other applications. + # We just want to test that the difference between psutil result + # and sysctl's is not too high. + p = subprocess.Popen("sysctl vm.vmtotal", shell=1, stdout=subprocess.PIPE) + result = p.communicate()[0].strip() + if sys.version_info >= (3,): + result = str(result, sys.stdout.encoding) + _, sysctl_avail_virtmem = parse_sysctl_vmtotal(result) + psutil_avail_virtmem = psutil.avail_virtmem() + difference = abs(sysctl_avail_virtmem - psutil_avail_virtmem) + # let's assume the test is failed if difference is > 0.5 MB + if difference > (0.5 * 2**20): + self.fail("sysctl=%s; psutil=%s; difference=%s;" %( + sysctl_avail_virtmem, psutil_avail_virtmem, difference)) + + def test_cached_mem(self): + sysctl_mem = sysctl("sysctl vm.stats.vm.v_cache_count") + psutil_mem = psutil.cached_mem() + self.assertEqual(sysctl_mem, psutil_mem) + + def test_process_create_time(self): + cmdline = "ps -o lstart -p %s" %self.pid + p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE) + output = p.communicate()[0] + if sys.version_info >= (3,): + output = str(output, sys.stdout.encoding) + start_ps = output.replace('STARTED', '').strip() + start_psutil = psutil.Process(self.pid).create_time + start_psutil = time.strftime("%a %b %e %H:%M:%S %Y", + time.localtime(start_psutil)) + self.assertEqual(start_ps, start_psutil) + + +if __name__ == '__main__': + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(BSDSpecificTestCase)) + unittest.TextTestRunner(verbosity=2).run(test_suite) + + + + diff --git a/test/_linux.py b/test/_linux.py index c29ebc7b..f60c33fc 100644 --- a/test/_linux.py +++ b/test/_linux.py @@ -1,24 +1,24 @@ -#!/usr/bin/env python
-#
-# $Id$
-#
-
-import unittest
-import subprocess
-import time
-
-import psutil
-
-from test_psutil import PYTHON, DEVNULL, reap_children
-from _posix import ps
-
-
-class LinuxSpecificTestCase(unittest.TestCase):
-
- def setUp(self):
- self.pid = subprocess.Popen(PYTHON, stdout=DEVNULL, stderr=DEVNULL).pid
-
- def tearDown(self):
- reap_children()
-
-
+#!/usr/bin/env python +# +# $Id$ +# + +import unittest +import subprocess +import time + +import psutil + +from test_psutil import PYTHON, DEVNULL, reap_children +from _posix import ps + + +class LinuxSpecificTestCase(unittest.TestCase): + + def setUp(self): + self.pid = subprocess.Popen(PYTHON, stdout=DEVNULL, stderr=DEVNULL).pid + + def tearDown(self): + reap_children() + + diff --git a/test/_osx.py b/test/_osx.py index 41818d93..3192448b 100644 --- a/test/_osx.py +++ b/test/_osx.py @@ -1,64 +1,64 @@ -#!/usr/bin/env python
-#
-# $Id$
-#
-
-import unittest
-import subprocess
-import time
-import re
-import sys
-
-import psutil
-
-from test_psutil import reap_children, PYTHON, DEVNULL
-#from _posix import ps
-
-
-def sysctl(cmdline):
- """Expects a sysctl command with an argument and parse the result
- returning only the value of interest.
- """
- p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE)
- result = p.communicate()[0].strip().split()[1]
- if sys.version_info >= (3,):
- result = str(result, sys.stdout.encoding)
- try:
- return int(result)
- except ValueError:
- return result
-
-
-class OSXSpecificTestCase(unittest.TestCase):
-
- def setUp(self):
- self.pid = subprocess.Popen(PYTHON, stdout=DEVNULL, stderr=DEVNULL).pid
-
- def tearDown(self):
- reap_children()
-
- def test_TOTAL_PHYMEM(self):
- sysctl_hwphymem = sysctl('sysctl hw.physmem')
- self.assertEqual(sysctl_hwphymem, psutil.TOTAL_PHYMEM)
-
- def test_process_create_time(self):
- cmdline = "ps -o lstart -p %s" %self.pid
- p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE)
- output = p.communicate()[0]
- if sys.version_info >= (3,):
- output = str(output, sys.stdout.encoding)
- start_ps = output.replace('STARTED', '').strip()
- start_psutil = psutil.Process(self.pid).create_time
- start_psutil = time.strftime("%a %b %e %H:%M:%S %Y",
- time.localtime(start_psutil))
- self.assertEqual(start_ps, start_psutil)
-
-
-if __name__ == '__main__':
- test_suite = unittest.TestSuite()
- test_suite.addTest(unittest.makeSuite(OSXSpecificTestCase))
- unittest.TextTestRunner(verbosity=2).run(test_suite)
-
-
-
-
+#!/usr/bin/env python +# +# $Id$ +# + +import unittest +import subprocess +import time +import re +import sys + +import psutil + +from test_psutil import reap_children, PYTHON, DEVNULL +#from _posix import ps + + +def sysctl(cmdline): + """Expects a sysctl command with an argument and parse the result + returning only the value of interest. + """ + p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE) + result = p.communicate()[0].strip().split()[1] + if sys.version_info >= (3,): + result = str(result, sys.stdout.encoding) + try: + return int(result) + except ValueError: + return result + + +class OSXSpecificTestCase(unittest.TestCase): + + def setUp(self): + self.pid = subprocess.Popen(PYTHON, stdout=DEVNULL, stderr=DEVNULL).pid + + def tearDown(self): + reap_children() + + def test_TOTAL_PHYMEM(self): + sysctl_hwphymem = sysctl('sysctl hw.physmem') + self.assertEqual(sysctl_hwphymem, psutil.TOTAL_PHYMEM) + + def test_process_create_time(self): + cmdline = "ps -o lstart -p %s" %self.pid + p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE) + output = p.communicate()[0] + if sys.version_info >= (3,): + output = str(output, sys.stdout.encoding) + start_ps = output.replace('STARTED', '').strip() + start_psutil = psutil.Process(self.pid).create_time + start_psutil = time.strftime("%a %b %e %H:%M:%S %Y", + time.localtime(start_psutil)) + self.assertEqual(start_ps, start_psutil) + + +if __name__ == '__main__': + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(OSXSpecificTestCase)) + unittest.TextTestRunner(verbosity=2).run(test_suite) + + + + diff --git a/test/_posix.py b/test/_posix.py index 11a1d8a9..82e98a00 100755 --- a/test/_posix.py +++ b/test/_posix.py @@ -1,136 +1,136 @@ -#!/usr/bin/env python
-#
-# $Id$
-#
-
-import unittest
-import subprocess
-import time
-import sys
-import os
-
-import psutil
-
-from test_psutil import kill, PYTHON, DEVNULL
-
-
-def ps(cmd):
- """Expects a ps command with a -o argument and parse the result
- returning only the value of interest.
- """
- if not sys.platform.lower().startswith("linux"):
- cmd = cmd.replace(" --no-headers ", " ")
- p = subprocess.Popen(cmd, shell=1, stdout=subprocess.PIPE)
- output = p.communicate()[0].strip()
- if sys.version_info >= (3,):
- output = str(output, sys.stdout.encoding)
- if not sys.platform.lower().startswith("linux"):
- output = output.split('\n')[1]
- try:
- return int(output)
- except ValueError:
- return output
-
-
-class PosixSpecificTestCase(unittest.TestCase):
- """Compare psutil results against 'ps' command line utility."""
-
- # for ps -o arguments see: http://unixhelp.ed.ac.uk/CGI/man-cgi?ps
-
- def setUp(self):
- self.pid = subprocess.Popen([PYTHON, "-E", "-O"], stdout=DEVNULL, stderr=DEVNULL).pid
-
- def tearDown(self):
- kill(self.pid)
-
- def test_process_parent_pid(self):
- ppid_ps = ps("ps --no-headers -o ppid -p %s" %self.pid)
- ppid_psutil = psutil.Process(self.pid).ppid
- self.assertEqual(ppid_ps, ppid_psutil)
-
- def test_process_uid(self):
- uid_ps = ps("ps --no-headers -o uid -p %s" %self.pid)
- uid_psutil = psutil.Process(self.pid).uid
- self.assertEqual(uid_ps, uid_psutil)
-
- def test_process_gid(self):
- gid_ps = ps("ps --no-headers -o rgid -p %s" %self.pid)
- gid_psutil = psutil.Process(self.pid).gid
- self.assertEqual(gid_ps, gid_psutil)
-
- def test_process_username(self):
- username_ps = ps("ps --no-headers -o user -p %s" %self.pid)
- username_psutil = psutil.Process(self.pid).username
- self.assertEqual(username_ps, username_psutil)
-
- def test_process_rss_memory(self):
- # give python interpreter some time to properly initialize
- # so that the results are the same
- time.sleep(0.1)
- rss_ps = ps("ps --no-headers -o rss -p %s" %self.pid)
- rss_psutil = psutil.Process(self.pid).get_memory_info()[0] / 1024
- self.assertEqual(rss_ps, rss_psutil)
-
- def test_process_vsz_memory(self):
- # give python interpreter some time to properly initialize
- # so that the results are the same
- time.sleep(0.1)
- vsz_ps = ps("ps --no-headers -o vsz -p %s" %self.pid)
- vsz_psutil = psutil.Process(self.pid).get_memory_info()[1] / 1024
- self.assertEqual(vsz_ps, vsz_psutil)
-
- def test_process_name(self):
- # use command + arg since "comm" keyword not supported on all platforms
- name_ps = ps("ps --no-headers -o command -p %s" %self.pid).split(' ')[0]
- # remove path if there is any, from the command
- name_ps = os.path.basename(name_ps)
- name_psutil = psutil.Process(self.pid).name
- self.assertEqual(name_ps, name_psutil)
-
- def test_process_pathname(self):
- ps_pathname = ps("ps --no-headers -o command -p %s" %self.pid).split(' ')[0]
- psutil_pathname = os.path.join(psutil.Process(self.pid).path,
- psutil.Process(self.pid).name)
- self.assertEqual(ps_pathname, psutil_pathname)
-
- def test_process_cmdline(self):
- ps_cmdline = ps("ps --no-headers -o command -p %s" %self.pid)
- psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline)
- self.assertEqual(ps_cmdline, psutil_cmdline)
-
- def test_get_pids(self):
- # Note: this test might fail if the OS is starting/killing
- # other processes in the meantime
- p = subprocess.Popen(["ps", "ax", "-o", "pid"], stdout=subprocess.PIPE)
- output = p.communicate()[0].strip()
- if sys.version_info >= (3,):
- output = str(output, sys.stdout.encoding)
- output = output.replace('PID', '')
- p.wait()
- pids_ps = []
- for pid in output.split('\n'):
- if pid:
- pids_ps.append(int(pid.strip()))
- # remove ps subprocess pid which is supposed to be dead in meantime
- pids_ps.remove(p.pid)
- # not all systems include pid 0 in their list but psutil does so
- # we force it
- if 0 not in pids_ps:
- pids_ps.append(0)
-
- pids_psutil = psutil.get_pid_list()
- pids_ps.sort()
- pids_psutil.sort()
-
- if pids_ps != pids_psutil:
- difference = filter(lambda x:x not in pids_ps, pids_psutil) + \
- filter(lambda x:x not in pids_psutil, pids_ps)
- self.fail("difference: " + str(difference))
-
-
-if __name__ == '__main__':
- test_suite = unittest.TestSuite()
- test_suite.addTest(unittest.makeSuite(PosixSpecificTestCase))
- unittest.TextTestRunner(verbosity=2).run(test_suite)
-
-
+#!/usr/bin/env python +# +# $Id$ +# + +import unittest +import subprocess +import time +import sys +import os + +import psutil + +from test_psutil import kill, PYTHON, DEVNULL + + +def ps(cmd): + """Expects a ps command with a -o argument and parse the result + returning only the value of interest. + """ + if not sys.platform.lower().startswith("linux"): + cmd = cmd.replace(" --no-headers ", " ") + p = subprocess.Popen(cmd, shell=1, stdout=subprocess.PIPE) + output = p.communicate()[0].strip() + if sys.version_info >= (3,): + output = str(output, sys.stdout.encoding) + if not sys.platform.lower().startswith("linux"): + output = output.split('\n')[1] + try: + return int(output) + except ValueError: + return output + + +class PosixSpecificTestCase(unittest.TestCase): + """Compare psutil results against 'ps' command line utility.""" + + # for ps -o arguments see: http://unixhelp.ed.ac.uk/CGI/man-cgi?ps + + def setUp(self): + self.pid = subprocess.Popen([PYTHON, "-E", "-O"], stdout=DEVNULL, stderr=DEVNULL).pid + + def tearDown(self): + kill(self.pid) + + def test_process_parent_pid(self): + ppid_ps = ps("ps --no-headers -o ppid -p %s" %self.pid) + ppid_psutil = psutil.Process(self.pid).ppid + self.assertEqual(ppid_ps, ppid_psutil) + + def test_process_uid(self): + uid_ps = ps("ps --no-headers -o uid -p %s" %self.pid) + uid_psutil = psutil.Process(self.pid).uid + self.assertEqual(uid_ps, uid_psutil) + + def test_process_gid(self): + gid_ps = ps("ps --no-headers -o rgid -p %s" %self.pid) + gid_psutil = psutil.Process(self.pid).gid + self.assertEqual(gid_ps, gid_psutil) + + def test_process_username(self): + username_ps = ps("ps --no-headers -o user -p %s" %self.pid) + username_psutil = psutil.Process(self.pid).username + self.assertEqual(username_ps, username_psutil) + + def test_process_rss_memory(self): + # give python interpreter some time to properly initialize + # so that the results are the same + time.sleep(0.1) + rss_ps = ps("ps --no-headers -o rss -p %s" %self.pid) + rss_psutil = psutil.Process(self.pid).get_memory_info()[0] / 1024 + self.assertEqual(rss_ps, rss_psutil) + + def test_process_vsz_memory(self): + # give python interpreter some time to properly initialize + # so that the results are the same + time.sleep(0.1) + vsz_ps = ps("ps --no-headers -o vsz -p %s" %self.pid) + vsz_psutil = psutil.Process(self.pid).get_memory_info()[1] / 1024 + self.assertEqual(vsz_ps, vsz_psutil) + + def test_process_name(self): + # use command + arg since "comm" keyword not supported on all platforms + name_ps = ps("ps --no-headers -o command -p %s" %self.pid).split(' ')[0] + # remove path if there is any, from the command + name_ps = os.path.basename(name_ps) + name_psutil = psutil.Process(self.pid).name + self.assertEqual(name_ps, name_psutil) + + def test_process_pathname(self): + ps_pathname = ps("ps --no-headers -o command -p %s" %self.pid).split(' ')[0] + psutil_pathname = os.path.join(psutil.Process(self.pid).path, + psutil.Process(self.pid).name) + self.assertEqual(ps_pathname, psutil_pathname) + + def test_process_cmdline(self): + ps_cmdline = ps("ps --no-headers -o command -p %s" %self.pid) + psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline) + self.assertEqual(ps_cmdline, psutil_cmdline) + + def test_get_pids(self): + # Note: this test might fail if the OS is starting/killing + # other processes in the meantime + p = subprocess.Popen(["ps", "ax", "-o", "pid"], stdout=subprocess.PIPE) + output = p.communicate()[0].strip() + if sys.version_info >= (3,): + output = str(output, sys.stdout.encoding) + output = output.replace('PID', '') + p.wait() + pids_ps = [] + for pid in output.split('\n'): + if pid: + pids_ps.append(int(pid.strip())) + # remove ps subprocess pid which is supposed to be dead in meantime + pids_ps.remove(p.pid) + # not all systems include pid 0 in their list but psutil does so + # we force it + if 0 not in pids_ps: + pids_ps.append(0) + + pids_psutil = psutil.get_pid_list() + pids_ps.sort() + pids_psutil.sort() + + if pids_ps != pids_psutil: + difference = filter(lambda x:x not in pids_ps, pids_psutil) + \ + filter(lambda x:x not in pids_psutil, pids_ps) + self.fail("difference: " + str(difference)) + + +if __name__ == '__main__': + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(PosixSpecificTestCase)) + unittest.TextTestRunner(verbosity=2).run(test_suite) + + diff --git a/test/_windows.py b/test/_windows.py index 0d6fcb4b..bcd9abec 100644 --- a/test/_windows.py +++ b/test/_windows.py @@ -1,144 +1,144 @@ -#!/usr/bin/env python
-#
-# $Id$
-#
-
-
-import os
-import unittest
-import platform
-import subprocess
-import signal
-import time
-import warnings
-
-import psutil
-from test_psutil import reap_children, PYTHON, DEVNULL
-try:
- from psutil import wmi
-except ImportError:
- warnings.warn("Can't import WMI module; Windows specific tests disabled",
- RuntimeWarning)
- wmi = None
-
-
-class WindowsSpecificTestCase(unittest.TestCase):
-
- def setUp(self):
- self.pid = subprocess.Popen([PYTHON, "-E", "-O"], stdout=DEVNULL, stderr=DEVNULL).pid
-
- def tearDown(self):
- reap_children()
-
- def test_issue_24(self):
- p = psutil.Process(0)
- self.assertRaises(psutil.AccessDenied, p.kill)
-
- def test_pid_4(self):
- p = psutil.Process(4)
- self.assertEqual(p.name, 'System')
- # use __str__ to access all common Process properties to check
- # that nothing strange happens
- str(p)
- p.username
- self.assertTrue(p.create_time >= 0.0)
- try:
- rss, vms = p.get_memory_info()
- except psutil.AccessDenied:
- # expected on Windows Vista and Windows 7
- if not platform.uname()[1] in ('vista', 'win-7'):
- raise
- else:
- self.assertTrue(rss > 0)
- self.assertEqual(vms, 0)
-
- def test_signal(self):
- p = psutil.Process(self.pid)
- self.assertRaises(ValueError, p.send_signal, signal.SIGINT)
-
- if wmi is not None:
-
- # --- Process class tests
-
- def test_process_name(self):
- w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
- p = psutil.Process(self.pid)
- self.assertEqual(p.name, w.Caption)
-
- def test_process_path(self):
- w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
- p = psutil.Process(self.pid)
- self.assertEqual(os.path.join(p.path, p.name), w.ExecutablePath)
-
- def test_process_cmdline(self):
- w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
- p = psutil.Process(self.pid)
- self.assertEqual(' '.join(p.cmdline), w.CommandLine)
-
- def test_process_username(self):
- w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
- p = psutil.Process(self.pid)
- domain, _, username = w.GetOwner()
- username = "%s\\%s" %(domain, username)
- self.assertEqual(p.username, username)
-
- def test_process_rss_memory(self):
- w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
- p = psutil.Process(self.pid)
- rss = p.get_memory_info()[0]
- self.assertEqual(rss, int(w.WorkingSetSize))
-
- def test_process_vsz_memory(self):
- w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
- p = psutil.Process(self.pid)
- vsz = p.get_memory_info()[1]
- self.assertEqual(vsz, int(w.PageFileUsage) * 1024)
-
- def test_process_create_time(self):
- w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
- p = psutil.Process(self.pid)
- wmic_create = str(w.CreationDate.split('.')[0])
- psutil_create = time.strftime("%Y%m%d%H%M%S",
- time.localtime(p.create_time))
- self.assertEqual(wmic_create, psutil_create)
-
-
- # --- psutil namespace functions and constants tests
-
- def test_NUM_CPUS(self):
- num_cpus = int(os.environ['NUMBER_OF_PROCESSORS'])
- self.assertEqual(num_cpus, psutil.NUM_CPUS)
-
- def test_TOTAL_PHYMEM(self):
- w = wmi.WMI().Win32_ComputerSystem()[0]
- self.assertEqual(int(w.TotalPhysicalMemory), psutil.TOTAL_PHYMEM)
-
- def test__UPTIME(self):
- # _UPTIME constant is not public but it is used internally
- # as value to return for pid 0 creation time.
- # WMI behaves the same.
- w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0]
- p = psutil.Process(0)
- wmic_create = str(w.CreationDate.split('.')[0])
- psutil_create = time.strftime("%Y%m%d%H%M%S",
- time.localtime(p.create_time))
-
- def test_get_pids(self):
- # Note: this test might fail if the OS is starting/killing
- # other processes in the meantime
- w = wmi.WMI().Win32_Process()
- wmi_pids = [x.ProcessId for x in w]
- wmi_pids.sort()
- psutil_pids = psutil.get_pid_list()
- psutil_pids.sort()
- if wmi_pids != psutil_pids:
- difference = filter(lambda x:x not in wmi_pids, psutil_pids) + \
- filter(lambda x:x not in psutil_pids, wmi_pids)
- self.fail("difference: " + str(difference))
-
-
-if __name__ == '__main__':
- test_suite = unittest.TestSuite()
- test_suite.addTest(unittest.makeSuite(WindowsSpecificTestCase))
- unittest.TextTestRunner(verbosity=2).run(test_suite)
-
+#!/usr/bin/env python +# +# $Id$ +# + + +import os +import unittest +import platform +import subprocess +import signal +import time +import warnings + +import psutil +from test_psutil import reap_children, PYTHON, DEVNULL +try: + from psutil import wmi +except ImportError: + warnings.warn("Can't import WMI module; Windows specific tests disabled", + RuntimeWarning) + wmi = None + + +class WindowsSpecificTestCase(unittest.TestCase): + + def setUp(self): + self.pid = subprocess.Popen([PYTHON, "-E", "-O"], stdout=DEVNULL, stderr=DEVNULL).pid + + def tearDown(self): + reap_children() + + def test_issue_24(self): + p = psutil.Process(0) + self.assertRaises(psutil.AccessDenied, p.kill) + + def test_pid_4(self): + p = psutil.Process(4) + self.assertEqual(p.name, 'System') + # use __str__ to access all common Process properties to check + # that nothing strange happens + str(p) + p.username + self.assertTrue(p.create_time >= 0.0) + try: + rss, vms = p.get_memory_info() + except psutil.AccessDenied: + # expected on Windows Vista and Windows 7 + if not platform.uname()[1] in ('vista', 'win-7'): + raise + else: + self.assertTrue(rss > 0) + self.assertEqual(vms, 0) + + def test_signal(self): + p = psutil.Process(self.pid) + self.assertRaises(ValueError, p.send_signal, signal.SIGINT) + + if wmi is not None: + + # --- Process class tests + + def test_process_name(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + self.assertEqual(p.name, w.Caption) + + def test_process_path(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + self.assertEqual(os.path.join(p.path, p.name), w.ExecutablePath) + + def test_process_cmdline(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + self.assertEqual(' '.join(p.cmdline), w.CommandLine) + + def test_process_username(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + domain, _, username = w.GetOwner() + username = "%s\\%s" %(domain, username) + self.assertEqual(p.username, username) + + def test_process_rss_memory(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + rss = p.get_memory_info()[0] + self.assertEqual(rss, int(w.WorkingSetSize)) + + def test_process_vsz_memory(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + vsz = p.get_memory_info()[1] + self.assertEqual(vsz, int(w.PageFileUsage) * 1024) + + def test_process_create_time(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + wmic_create = str(w.CreationDate.split('.')[0]) + psutil_create = time.strftime("%Y%m%d%H%M%S", + time.localtime(p.create_time)) + self.assertEqual(wmic_create, psutil_create) + + + # --- psutil namespace functions and constants tests + + def test_NUM_CPUS(self): + num_cpus = int(os.environ['NUMBER_OF_PROCESSORS']) + self.assertEqual(num_cpus, psutil.NUM_CPUS) + + def test_TOTAL_PHYMEM(self): + w = wmi.WMI().Win32_ComputerSystem()[0] + self.assertEqual(int(w.TotalPhysicalMemory), psutil.TOTAL_PHYMEM) + + def test__UPTIME(self): + # _UPTIME constant is not public but it is used internally + # as value to return for pid 0 creation time. + # WMI behaves the same. + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(0) + wmic_create = str(w.CreationDate.split('.')[0]) + psutil_create = time.strftime("%Y%m%d%H%M%S", + time.localtime(p.create_time)) + + def test_get_pids(self): + # Note: this test might fail if the OS is starting/killing + # other processes in the meantime + w = wmi.WMI().Win32_Process() + wmi_pids = [x.ProcessId for x in w] + wmi_pids.sort() + psutil_pids = psutil.get_pid_list() + psutil_pids.sort() + if wmi_pids != psutil_pids: + difference = filter(lambda x:x not in wmi_pids, psutil_pids) + \ + filter(lambda x:x not in psutil_pids, wmi_pids) + self.fail("difference: " + str(difference)) + + +if __name__ == '__main__': + test_suite = unittest.TestSuite() + test_suite.addTest(unittest.makeSuite(WindowsSpecificTestCase)) + unittest.TextTestRunner(verbosity=2).run(test_suite) + diff --git a/test/test_psutil.py b/test/test_psutil.py index 91052175..647362c9 100644 --- a/test/test_psutil.py +++ b/test/test_psutil.py @@ -43,8 +43,8 @@ def kill(pid): psutil.Process(pid).kill() def reap_children(): - """Kill any subprocess started by this test suite and ensure that - no zombies stick around to hog resources and create problems when + """Kill any subprocess started by this test suite and ensure that + no zombies stick around to hog resources and create problems when looking for refleaks. """ if os.name == 'posix': @@ -552,7 +552,7 @@ class TestCase(unittest.TestCase): if os.name == 'posix': if hasattr(os, 'getuid') and os.getuid() > 0: def test_unix_access_denied(self): - p = psutil.Process(1) + p = psutil.Process(1) self.assertRaises(psutil.AccessDenied, p.kill) self.assertRaises(psutil.AccessDenied, p.send_signal, signal.SIGTERM) self.assertRaises(psutil.AccessDenied, p.terminate) @@ -582,7 +582,7 @@ if hasattr(os, 'getuid'): if sys.platform.lower().startswith("linux"): - # overridden tests known to raise AccessDenied when run + # overridden tests known to raise AccessDenied when run # as limited user def test_getcwd(self): self.assertRaises(psutil.AccessDenied, TestCase.test_getcwd, self) |