Skip to content

Commit

Permalink
#795 / win services: add bin path
Browse files Browse the repository at this point in the history
  • Loading branch information
giampaolo committed Mar 6, 2016
1 parent a93bac9 commit 3a5f60f
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 7 deletions.
21 changes: 18 additions & 3 deletions psutil/_pswindows.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,14 @@ def users():
class WindowsService(object):
"""Represents an installed Windows service."""

def __init__(self, name, display_name, status, pid):
def __init__(self, name, display_name, status, pid, binpath):
self._name = name
self._display_name = display_name
self._status = status
if pid == 0:
pid = None
self._pid = pid
self._binpath = binpath

def __str__(self):
details = "(name=%s, status=%s, pid=%s)" % (
Expand All @@ -356,11 +357,25 @@ def display_name(self):
def status(self):
return SERVICE_STATUSES.get(self._status, self._status)

@property
def binpath(self):
return self._binpath

def as_dict(self):
return dict(
pid=self.pid,
name=self.name,
display_name=self.display_name,
status=self.status,
binpath=self.binpath,
)


def win_service_iter():
"""Return a list of WindowsService instances."""
for name, display_name, status, pid in cext.winservice_enumerate():
yield WindowsService(name, display_name, status, pid)
ret = cext.winservice_enumerate()
for name, display_name, status, pid, binpath in ret:
yield WindowsService(name, display_name, status, pid, binpath)


# --- decorators
Expand Down
44 changes: 40 additions & 4 deletions psutil/arch/windows/services.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ psutil_winservice_enumerate(PyObject *self, PyObject *args) {
DWORD resumeHandle = 0;
DWORD dwBytes = 0;
DWORD i;
SC_HANDLE hService = NULL;
QUERY_SERVICE_CONFIG *qsc = NULL;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;

Expand All @@ -40,7 +42,7 @@ psutil_winservice_enumerate(PyObject *self, PyObject *args) {
ok = EnumServicesStatusEx(
sc,
SC_ENUM_PROCESS_INFO,
SERVICE_WIN32,
SERVICE_WIN32, // XXX - extend this to include drivers etc.?
SERVICE_STATE_ALL,
(LPBYTE)lpService,
dwBytes,
Expand All @@ -57,18 +59,48 @@ psutil_winservice_enumerate(PyObject *self, PyObject *args) {
}

for (i = 0; i < srvCount; i++) {
// Get service handler.
hService = OpenService(sc, lpService[i].lpServiceName,
SERVICE_QUERY_CONFIG);
if (hService == NULL) {
PyErr_SetFromWindowsErr(0);
goto error;
}

// Query service config to get the binary path. First call to
// QueryServiceConfig() is necessary to get the right size.
bytesNeeded = 0;
QueryServiceConfig(hService, NULL, 0, &bytesNeeded);
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
PyErr_SetFromWindowsErr(0);
goto error;
}
qsc = (QUERY_SERVICE_CONFIG *)malloc(bytesNeeded);
ok = QueryServiceConfig(hService, qsc, bytesNeeded, &bytesNeeded);
if (ok == 0) {
PyErr_SetFromWindowsErr(0);
goto error;
}

// Construct the result.
py_tuple = Py_BuildValue(
"(ssik)",
"(ssiks)",
lpService[i].lpServiceName, // name
lpService[i].lpDisplayName, // display name
lpService[i].lpDisplayName, // display_name
lpService[i].ServiceStatusProcess.dwCurrentState, // status
lpService[i].ServiceStatusProcess.dwProcessId // pid
lpService[i].ServiceStatusProcess.dwProcessId, // pid
// TODO: handle encoding errs
qsc->lpBinaryPathName // binpath
);
if (py_tuple == NULL)
goto error;
if (PyList_Append(py_retlist, py_tuple))
goto error;
Py_DECREF(py_tuple);

// free stuff
CloseServiceHandle(hService);
free(qsc);
}

CloseServiceHandle(sc);
Expand All @@ -78,6 +110,10 @@ psutil_winservice_enumerate(PyObject *self, PyObject *args) {
error:
Py_XDECREF(py_tuple);
Py_DECREF(py_retlist);
if (hService != NULL)
CloseServiceHandle(hService);
if (qsc != NULL)
free(qsc);
if (sc != NULL)
CloseServiceHandle(sc);
if (lpService != NULL)
Expand Down
1 change: 1 addition & 0 deletions psutil/tests/test_windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ def test_win_service_iter(self):
self.assertIn(serv.status, statuses)
if serv.pid is not None:
psutil.Process(serv.pid)
serv.binpath


if __name__ == '__main__':
Expand Down

0 comments on commit 3a5f60f

Please sign in to comment.