3

I have used this question to learn install my python script as a service with ActivePython. I am able to install my script and remove it, as I would expect, but my problem is that once I start the script running, I then lose the ability to stop it or remove it. It just runs permanently and I cannot get rid of it. The answer to the linked question mentions checking a flag to stop the script. Can someone explain how to do this?

Right now the script does very little. just prints lines to a file every few seconds. I want to get it working before I move on to more complicated things.

import pythoncom
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import time


class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "PythonTest"
    _svc_display_name_ = "Python Test"
    _svc_description_ = "This is a test of installing Python services"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)
        socket.setdefaulttimeout(60)

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)

    def SvcDoRun(self):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                          servicemanager.PYS_SERVICE_STARTED,
                          (self._svc_name_,''))
        self.main()

    def main(self):
        i=0
        while True:
            f=open("C:\\hello.txt","a")
            f.write("hello"+str(i)+"\n")
            f.close()
            i=i+1
            time.sleep(5)


if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)
1
  • I might suggest that this ActiveState recipe simplifies writing simple Windows services greatly. Commented Oct 28, 2011 at 15:07

2 Answers 2

6

Of course you can't stop it, you're stuck in an infinite loop. Replace:

time.sleep(5)

with this:

if win32event.WaitForSingleObject(self.hWaitStop, 5000) == win32event.WAIT_OBJECT_0: 
    break

Should do the trick.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. That worked. Any idea how to get rid of the service that I installed before I fixed this?
If you edited the script and relaunched the service the new code should take over. If you're talking about instances of the previous version, just launch Task Manager (Ctrl+Shift+Escape) and kill the relevant processes; they should be named after your script. Or reboot :)
While I'm at it, a more detailed explanation: the SvcDoRun method is actually run in a thread that is separate from the one which called init. When the service manager calls SvcStop, it's still in another thread. So you have to set the event in SvcStop but also check if it's set in SvcDoRun in order to exit the thread when Windows tells you to.
0

"Checking a flag" means having the script (inside the while True loop) look for something, almost anything, as a signal to break out of the loop. It could check for the existence of a file with a particular name and exit when the file is created. As long as you can manually or through a control application create the signal, the service can look for that same signal.

As far as "not being able to stop it", do you mean that it keeps running even if you try to kill it with the Windows task manager?

1 Comment

Presumably @ewok means that the service cannot be stopped using the services control panel or net stop and it's ilk, since with an infinite loop, the service will just continue running.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.