summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-04-10 18:44:43 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2016-04-10 18:44:43 +0200
commitf5865347037b779b94d56aaf23c05d8276857a9e (patch)
tree713fe76bcfeb88f155d9ee4a5408229b6feb3f41
parentfc5753fd51134d7b838ed457c2253e71090bdad1 (diff)
downloadpsutil-f5865347037b779b94d56aaf23c05d8276857a9e.tar.gz
add winservice script and disablr start() and stop() methods
-rw-r--r--docs/index.rst2
-rw-r--r--psutil/__init__.py39
-rw-r--r--psutil/_pswindows.py60
-rw-r--r--psutil/arch/windows/services.c2
-rw-r--r--psutil/tests/test_windows.py16
-rw-r--r--scripts/winservices.py56
6 files changed, 131 insertions, 44 deletions
diff --git a/docs/index.rst b/docs/index.rst
index 2c831d85..c932de12 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1489,7 +1489,7 @@ Windows services
.. function:: win_service_iter()
Return an iterator yielding a :class:`WindowsService` class instance for all
- installed Windows services.
+ Windows services installed.
.. versionadded:: 4.2.0
Availability: Windows
diff --git a/psutil/__init__.py b/psutil/__init__.py
index d562cf57..832acd2a 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -1984,6 +1984,29 @@ def users():
return _psplatform.users()
+# =====================================================================
+# --- Windows services
+# =====================================================================
+
+
+if WINDOWS:
+
+ def win_service_iter():
+ """Return a generator yielding a WindowsService instance for all
+ Windows services installed.
+ """
+ return _psplatform.win_service_iter()
+
+ def win_service_get(name):
+ """Get a Windows service by name.
+ Raise NoSuchProcess if no service with such name exists.
+ """
+ return _psplatform.win_service_get(name)
+
+
+# =====================================================================
+
+
def test(): # pragma: no cover
"""List info of all currently running processes emulating ps aux
output.
@@ -2040,22 +2063,6 @@ def test(): # pragma: no cover
pinfo['name'].strip() or '?'))
-# =====================================================================
-# --- Windows services
-# =====================================================================
-
-if WINDOWS:
- def win_service_iter():
- """Return a generator yielding a WindowsService instance for all
- installed Windows services.
- """
- return _psplatform.win_service_iter()
-
- def win_service_get(name):
- """Get a Windows service by name."""
- return _psplatform.win_service_get(name)
-
-
del memoize, division, deprecated_method
if sys.version_info < (3, 0):
del num
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index 759574be..61947deb 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -39,7 +39,7 @@ else:
# process priority constants, import from __init__.py:
# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx
__extra__all__ = [
- "win_service_iter",
+ "win_service_iter", "win_service_get",
"ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
"HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS",
"NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS",
@@ -397,27 +397,43 @@ class WindowsService(object):
return d
# actions
-
- def start(self, timeout=None):
- with self._wrap_exceptions():
- cext.winservice_start(self.name())
- if timeout:
- giveup_at = time.time() + timeout
- while True:
- if self.status() == "running":
- return
- else:
- if time.time() > giveup_at:
- raise TimeoutExpired(timeout)
- else:
- time.sleep(.1)
-
- def stop(self):
- # Note: timeout is not implemented because it's just not
- # possible, see:
- # http://stackoverflow.com/questions/11973228/
- with self._wrap_exceptions():
- return cext.winservice_stop(self.name())
+ # XXX: the necessary C bindings for start() and stop() are implemented
+ # but for now I prefer not to expose them.
+ # I may change my mind in the future. Reasons:
+ # - they require Administrator privileges
+ # - can't implement a timeout for stop() (unless by using a thread,
+ # which sucks)
+ # - would require adding ServiceAlreadyStarted and
+ # ServiceAlreadyStopped exceptions, adding two new APIs.
+ # - we might also want to have modify(), which would basically mean
+ # rewriting win32serviceutil.ChangeServiceConfig, which involves a
+ # lot of stuff (and API constants which would pollute the API), see:
+ # http://pyxr.sourceforge.net/PyXR/c/python24/lib/site-packages/
+ # win32/lib/win32serviceutil.py.html#0175
+ # - psutil is tipically about "read only" monitoring stuff;
+ # win_service_* APIs should only be used to retrieve a service and
+ # check whether it's running
+
+ # def start(self, timeout=None):
+ # with self._wrap_exceptions():
+ # cext.winservice_start(self.name())
+ # if timeout:
+ # giveup_at = time.time() + timeout
+ # while True:
+ # if self.status() == "running":
+ # return
+ # else:
+ # if time.time() > giveup_at:
+ # raise TimeoutExpired(timeout)
+ # else:
+ # time.sleep(.1)
+
+ # def stop(self):
+ # # Note: timeout is not implemented because it's just not
+ # # possible, see:
+ # # http://stackoverflow.com/questions/11973228/
+ # with self._wrap_exceptions():
+ # return cext.winservice_stop(self.name())
def win_service_iter():
diff --git a/psutil/arch/windows/services.c b/psutil/arch/windows/services.c
index be1ef8f5..a2fe0bc5 100644
--- a/psutil/arch/windows/services.c
+++ b/psutil/arch/windows/services.c
@@ -356,6 +356,7 @@ error:
/*
* Start service.
+ * XXX - note: this is exposed but not used.
*/
PyObject *
psutil_winservice_start(PyObject *self, PyObject *args) {
@@ -387,6 +388,7 @@ error:
/*
* Stop service.
+ * XXX - note: this is exposed but not used.
*/
PyObject *
psutil_winservice_stop(PyObject *self, PyObject *args) {
diff --git a/psutil/tests/test_windows.py b/psutil/tests/test_windows.py
index 883e79c3..93225917 100644
--- a/psutil/tests/test_windows.py
+++ b/psutil/tests/test_windows.py
@@ -638,25 +638,31 @@ class TestServices(unittest.TestCase):
self.assertEqual(cm.exception.name, name + '???')
# test NoSuchProcess
- s = psutil.win_service_get(name)
+ service = psutil.win_service_get(name)
exc = WindowsError(
psutil._psplatform.cext.ERROR_SERVICE_DOES_NOT_EXIST, "")
with mock.patch("psutil._psplatform.cext.winservice_query_status",
side_effect=exc):
- self.assertRaises(psutil.NoSuchProcess, s.status)
+ self.assertRaises(psutil.NoSuchProcess, service.status)
with mock.patch("psutil._psplatform.cext.winservice_query_config",
side_effect=exc):
- self.assertRaises(psutil.NoSuchProcess, s.username)
+ self.assertRaises(psutil.NoSuchProcess, service.username)
# test AccessDenied
exc = WindowsError(
psutil._psplatform.cext.ERROR_ACCESS_DENIED, "")
with mock.patch("psutil._psplatform.cext.winservice_query_status",
side_effect=exc):
- self.assertRaises(psutil.AccessDenied, s.status)
+ self.assertRaises(psutil.AccessDenied, service.status)
with mock.patch("psutil._psplatform.cext.winservice_query_config",
side_effect=exc):
- self.assertRaises(psutil.AccessDenied, s.username)
+ self.assertRaises(psutil.AccessDenied, service.username)
+
+ # test __str__ and __repr__
+ self.assertIn(service.name(), str(service))
+ self.assertIn(service.display_name(), str(service))
+ self.assertIn(service.name(), repr(service))
+ self.assertIn(service.display_name(), repr(service))
if __name__ == '__main__':
diff --git a/scripts/winservices.py b/scripts/winservices.py
new file mode 100644
index 00000000..fed6a734
--- /dev/null
+++ b/scripts/winservices.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+List all Windows services installed.
+
+$ python scripts/winservices.py
+AeLookupSvc (Application Experience)
+status: stopped, start: manual, username: localSystem, pid: None
+binpath: C:\Windows\system32\svchost.exe -k netsvcs
+
+ALG (Application Layer Gateway Service)
+status: stopped, start: manual, username: NT AUTHORITY\LocalService, pid: None
+binpath: C:\Windows\System32\alg.exe
+
+APNMCP (Ask Update Service)
+status: running, start: automatic, username: LocalSystem, pid: 1108
+binpath: "C:\Program Files (x86)\AskPartnerNetwork\Toolbar\apnmcp.exe"
+
+AppIDSvc (Application Identity)
+status: stopped, start: manual, username: NT Authority\LocalService, pid: None
+binpath: C:\Windows\system32\svchost.exe -k LocalServiceAndNoImpersonation
+
+Appinfo (Application Information)
+status: stopped, start: manual, username: LocalSystem, pid: None
+binpath: C:\Windows\system32\svchost.exe -k netsvcs
+
+...
+"""
+
+
+import os
+import sys
+
+import psutil
+
+
+if os.name != 'nt':
+ sys.exit("platform not supported (Windows only)")
+
+
+def main():
+ for service in psutil.win_service_iter():
+ info = service.as_dict()
+ print("%s (%s)" % (info['name'], info['display_name']))
+ print("status: %s, start: %s, username: %s, pid: %s" % (
+ info['status'], info['start_type'], info['username'], info['pid']))
+ print("binpath: %s" % info['binpath'])
+ print("")
+
+
+if __name__ == '__main__':
+ sys.exit(main())