The WService Class is used for controlling WinNT, Win2k & WinXP like services. Just pass the name of the service you wish to control to the class instance and go from there.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | """
Module for manipulating WinNT, Win2k & WinXP services.
Requires the win32all package which can be retrieved
from => http://starship.python.net/crew/mhammond
"""
import sys, time
import win32api as wa, win32con as wc, win32service as ws
class WService:
"""
The WService Class is used for controlling WinNT, Win2k & WinXP like
services. Just pass the name of the service you wish to control to the
class instance and go from there. For example, if you want to control
the Workstation service try this:
import WService
workstation = WService.WService("Workstation")
workstation.start()
workstation.fetchstatus("running", 10)
workstation.stop()
workstation.fetchstatus("stopped")
Creating an instance of the WService class is done by passing the name of
the service as it appears in the Management Console or the short name as
it appears in the registry. Mixed case is ok.
cvs = WService.WService("CVS NT Service 1.11.1.2 (Build 41)")
or
cvs = WService.WService("cvs")
If needing remote service control try this:
cvs = WService.WService("cvs", r"\\CVS_SERVER")
or
cvs = WService.WService("cvs", "\\\\CVS_SERVER")
The WService Class supports these methods:
start: Starts service.
stop: Stops service.
restart: Stops and restarts service.
pause: Pauses service (Only if service supports feature).
resume: Resumes service that has been paused.
status: Queries current status of service.
fetchstatus: Continually queries service until requested status(STARTING, RUNNING,
STOPPING & STOPPED) is met or timeout value(in seconds) reached.
Default timeout value is infinite.
infotype: Queries service for process type. (Single, shared and/or
interactive process)
infoctrl: Queries control information about a running service.
i.e. Can it be paused, stopped, etc?
infostartup: Queries service Startup type. (Boot, System,
Automatic, Manual, Disabled)
setstartup Changes/sets Startup type. (Boot, System,
Automatic, Manual, Disabled)
getname: Gets the long and short service names used by Windows.
(Generally used for internal purposes)
"""
def __init__(self, service, machinename=None, dbname=None):
self.userv = service
self.scmhandle = ws.OpenSCManager(machinename, dbname, ws.SC_MANAGER_ALL_ACCESS)
self.sserv, self.lserv = self.getname()
if (self.sserv or self.lserv) == None: sys.exit()
self.handle = ws.OpenService(self.scmhandle, self.sserv, ws.SERVICE_ALL_ACCESS)
self.sccss = "SYSTEM\\CurrentControlSet\\Services\\"
def start(self):
ws.StartService(self.handle, None)
def stop(self):
self.stat = ws.ControlService(self.handle, ws.SERVICE_CONTROL_STOP)
def restart(self):
self.stop()
self.fetchstatus("STOPPED")
self.start()
def pause(self):
self.stat = ws.ControlService(self.handle, ws.SERVICE_CONTROL_PAUSE)
def resume(self):
self.stat = ws.ControlService(self.handle, ws.SERVICE_CONTROL_CONTINUE)
def status(self, prn = 0):
self.stat = ws.QueryServiceStatus(self.handle)
if self.stat[1]==ws.SERVICE_STOPPED:
if prn == 1:
print "The %s service is stopped." % self.lserv
else:
return "STOPPED"
elif self.stat[1]==ws.SERVICE_START_PENDING:
if prn == 1:
print "The %s service is starting." % self.lserv
else:
return "STARTING"
elif self.stat[1]==ws.SERVICE_STOP_PENDING:
if prn == 1:
print "The %s service is stopping." % self.lserv
else:
return "STOPPING"
elif self.stat[1]==ws.SERVICE_RUNNING:
if prn == 1:
print "The %s service is running." % self.lserv
else:
return "RUNNING"
def fetchstatus(self, fstatus, timeout=None):
self.fstatus = fstatus.upper()
if timeout != None:
timeout = int(timeout); timeout *= 2
def to(timeout):
time.sleep(.5)
if timeout != None:
if timeout > 1:
timeout -= 1; return timeout
else:
return "TO"
if self.fstatus == "STOPPED":
while 1:
self.stat = ws.QueryServiceStatus(self.handle)
if self.stat[1]==ws.SERVICE_STOPPED:
self.fstate = "STOPPED"; break
else:
timeout=to(timeout)
if timeout == "TO":
return "TIMEDOUT"; break
elif self.fstatus == "STOPPING":
while 1:
self.stat = ws.QueryServiceStatus(self.handle)
if self.stat[1]==ws.SERVICE_STOP_PENDING:
self.fstate = "STOPPING"; break
else:
timeout=to(timeout)
if timeout == "TO":
return "TIMEDOUT"; break
elif self.fstatus == "RUNNING":
while 1:
self.stat = ws.QueryServiceStatus(self.handle)
if self.stat[1]==ws.SERVICE_RUNNING:
self.fstate = "RUNNING"; break
else:
timeout=to(timeout)
if timeout == "TO":
return "TIMEDOUT"; break
elif self.fstatus == "STARTING":
while 1:
self.stat = ws.QueryServiceStatus(self.handle)
if self.stat[1]==ws.SERVICE_START_PENDING:
self.fstate = "STARTING"; break
else:
timeout=to(timeout)
if timeout == "TO":
return "TIMEDOUT"; break
def infotype(self):
self.stat = ws.QueryServiceStatus(self.handle)
if self.stat[0] and ws.SERVICE_WIN32_OWN_PROCESS:
print "The %s service runs in its own process." % self.lserv
if self.stat[0] and ws.SERVICE_WIN32_SHARE_PROCESS:
print "The %s service shares a process with other services." % self.lserv
if self.stat[0] and ws.SERVICE_INTERACTIVE_PROCESS:
print "The %s service can interact with the desktop." % self.lserv
def infoctrl(self):
self.stat = ws.QueryServiceStatus(self.handle)
if self.stat[2] and ws.SERVICE_ACCEPT_PAUSE_CONTINUE:
print "The %s service can be paused." % self.lserv
if self.stat[2] and ws.SERVICE_ACCEPT_STOP:
print "The %s service can be stopped." % self.lserv
if self.stat[2] and ws.SERVICE_ACCEPT_SHUTDOWN:
print "The %s service can be shutdown." % self.lserv
def infostartup(self):
self.isuphandle = wa.RegOpenKeyEx(wc.HKEY_LOCAL_MACHINE, self.sccss + self.sserv, 0, wc.KEY_READ)
self.isuptype = wa.RegQueryValueEx(self.isuphandle, "Start")[0]
wa.RegCloseKey(self.isuphandle)
if self.isuptype == 0:
return "boot"
elif self.isuptype == 1:
return "system"
elif self.isuptype == 2:
return "automatic"
elif self.isuptype == 3:
return "manual"
elif self.isuptype == 4:
return "disabled"
def setstartup(self, startuptype):
self.startuptype = startuptype.lower()
if self.startuptype == "boot":
self.suptype = 0
elif self.startuptype == "system":
self.suptype = 1
elif self.startuptype == "automatic":
self.suptype = 2
elif self.startuptype == "manual":
self.suptype = 3
elif self.startuptype == "disabled":
self.suptype = 4
self.snc = ws.SERVICE_NO_CHANGE
ws.ChangeServiceConfig(self.handle, self.snc, self.suptype, \
self.snc, None, None, 0, None, None, None, self.lserv)
def getname(self):
self.snames=ws.EnumServicesStatus(self.scmhandle)
for i in self.snames:
if i[0].lower() == self.userv.lower():
return i[0], i[1]; break
if i[1].lower() == self.userv.lower():
return i[0], i[1]; break
print "Error: The %s service doesn't seem to exist." % self.userv
return None, None
|
Using this class in python scripts makes it easy to control Windows services without reinventing the wheel every time. The ability to create a class instance of any desired service allows one to control services with very little logic. This class extends the inspired work of Mark Hammond, author of the win32all package and more, and andy mckay, cookbook contributor.
usage difficulties. The fetchstatus method can loop forever if you ask for the wrong status. The service name requires an exact match (case sensitive) to process a service. This is stricter than the underlying system functions.
Re: usage difficulties. It's true the fetchstatus method can run forever but I don't see that as a bad thing, do you? It's not often we have things that can last forever, so I say enjoy it and let it rip! ;-) Actually I've updated the method, it now supports a timeout argument but forever is still the default. For the hard corers out there! lol
The service name thingy... I thought "What's so hard about pulling the name out of the service control manager? Just double click on the service and then CTRL-C." when I wrote it. So I think the service name lookup is being a bit picky but it's been adjusted. It now supports long and short names with mixed cases. The feature in the win32serviceutil where it does the kinder, gentler service name lookup isn't that low level though. It uses some of the very code on this cookbook site. Look for the "Get the Windows service name from the long name" recipe, it's in the System Admin section. I'm not sure which came first though, the recipe or the win32serviceutil?
Thanks for the comments. Keep them coming! ;-)
Review status of remote servers. I wrote a small python hack using the sc.exe command to poll our Win2000 Domain Controller's Service status. I mainly look at ntfrs for File Replication. Would it be possible to add this ability to WService?
Re: Review status of remote servers. Good question. I've modified WService to work with remote machines but I'm not sure if it works correctly since I don't have a setup to properly test it. I believe the api depends on one or more services, namely the Server and possibly the RPC's and/or Remote Registry services, running on the remote machine. It would be great if you could test it and let me know if it works.
fetchstate(). fetchstate() is not declarated within this class but used in restart() method. I suppose it was renamed to fetchstatus() but restart() methdod was not renewed. In common looks matue, will use it :)
Raw input.. Hello,
I don't speak python or any other language. Could there be some thing like a raw input where computername/ip adress and servicename/procesid could be filled in. I can't figure it out with the comments, they're to poor for me, raise more questions then they answer.
Thanks!
There is a small mistake in the code. Once I changed "fetchstate" to "fetchstatus" the restart method worked fine.
The fetchstatus bug in the restart method has been fixed. It's amazing after 8+ yrs some folks are finding the code useful. Good to know.
@ ap anonypea, 13 years and counting! Used it for reference today on a service tool I'm building. Thanks!