From a93bac9880a1d8eda49821998d74505d0480fc6a Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Sun, 6 Mar 2016 13:51:05 -0800 Subject: [PATCH] #795 / win services: also return service PID --- psutil/_pswindows.py | 16 ++++++++++++---- psutil/arch/windows/services.c | 23 ++++++++++++++++------- psutil/tests/test_windows.py | 2 ++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py index e437e33ce..b49d36974 100644 --- a/psutil/_pswindows.py +++ b/psutil/_pswindows.py @@ -324,18 +324,26 @@ def users(): class WindowsService(object): """Represents an installed Windows service.""" - def __init__(self, name, display_name, status): + def __init__(self, name, display_name, status, pid): self._name = name self._display_name = display_name self._status = status + if pid == 0: + pid = None + self._pid = pid def __str__(self): - details = "(name=%s, status=%s)" % (self.name, self.status) + details = "(name=%s, status=%s, pid=%s)" % ( + self.name, self.status, self.pid) return "%s%s" % (self.__class__.__name__, details) def __repr__(self): return "<%s at %s>" % (self.__str__(), id(self)) + @property + def pid(self): + return self._pid + @property def name(self): return self._name @@ -351,8 +359,8 @@ def status(self): def win_service_iter(): """Return a list of WindowsService instances.""" - for name, display_name, status in cext.winservice_enumerate(): - yield WindowsService(name, display_name, status) + for name, display_name, status, pid in cext.winservice_enumerate(): + yield WindowsService(name, display_name, status, pid) # --- decorators diff --git a/psutil/arch/windows/services.c b/psutil/arch/windows/services.c index 61e0b217c..e8bdb3b5d 100644 --- a/psutil/arch/windows/services.c +++ b/psutil/arch/windows/services.c @@ -16,7 +16,7 @@ */ PyObject * psutil_winservice_enumerate(PyObject *self, PyObject *args) { - ENUM_SERVICE_STATUS *lpService = NULL; + ENUM_SERVICE_STATUS_PROCESS *lpService = NULL; SC_HANDLE sc = NULL; BOOL ok; DWORD bytesNeeded = 0; @@ -37,23 +37,32 @@ psutil_winservice_enumerate(PyObject *self, PyObject *args) { } for (;;) { - ok = EnumServicesStatus( - sc, SERVICE_WIN32, SERVICE_STATE_ALL, lpService, dwBytes, - &bytesNeeded, &srvCount, &resumeHandle); + ok = EnumServicesStatusEx( + sc, + SC_ENUM_PROCESS_INFO, + SERVICE_WIN32, + SERVICE_STATE_ALL, + (LPBYTE)lpService, + dwBytes, + &bytesNeeded, + &srvCount, + &resumeHandle, + NULL); if (ok || (GetLastError() != ERROR_MORE_DATA)) break; if (lpService) free(lpService); dwBytes = bytesNeeded; - lpService = (ENUM_SERVICE_STATUS*)malloc(dwBytes); + lpService = (ENUM_SERVICE_STATUS_PROCESS*)malloc(dwBytes); } for (i = 0; i < srvCount; i++) { py_tuple = Py_BuildValue( - "(ssi)", + "(ssik)", lpService[i].lpServiceName, // name lpService[i].lpDisplayName, // display name - lpService[i].ServiceStatus.dwCurrentState // status + lpService[i].ServiceStatusProcess.dwCurrentState, // status + lpService[i].ServiceStatusProcess.dwProcessId // pid ); if (py_tuple == NULL) goto error; diff --git a/psutil/tests/test_windows.py b/psutil/tests/test_windows.py index 6972e237c..4a9d0997d 100644 --- a/psutil/tests/test_windows.py +++ b/psutil/tests/test_windows.py @@ -593,6 +593,8 @@ def test_win_service_iter(self): self.assertTrue(serv.name) self.assertTrue(serv.display_name) self.assertIn(serv.status, statuses) + if serv.pid is not None: + psutil.Process(serv.pid) if __name__ == '__main__':