I have used configparser to read a configuration file in python. When the script is converted to Windows Service it is giving error saying "Error starting service: The service did not respond to the start or control request in a timely fashion."
I have increased ServicesPipeTimeout
and enabled Allow service to interact with desktop
but it did not solve the issue.
The script is
import logging
import configparser
import mysql.connector
import socket
import win32event
import win32service
import servicemanager
import win32serviceutil
import sys
logging.basicConfig(
filename = "C:\\Users\\Administrator\\PythonService.txt",
level = logging.INFO,
format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%m/%d/%Y %I:%M:%S %p'
)
def main():
configaration = configparser.ConfigParser()
configaration.read('default.ini')
host = configaration['mysql']['host']
username = configaration['mysql']['user']
password = configaration['mysql']['password']
database = configaration['mysql']['database']
config = {'user': username,'password': password,'host': host,'database': database}
logging.info(config)
class TestService(win32serviceutil.ServiceFramework):
_svc_name_ = "ClientService"
_svc_display_name_ = "Client Service"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(60)
self.stop_requested = False
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
logging.info('Stopping service ....')
self.stop_requested = True
def SvcDoRun(self):
logging.info("Started service")
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
rc = None
while rc != win32event.WAIT_OBJECT_0:
rc = win32event.WaitForSingleObject(self.hWaitStop, 5000)
if rc == win32event.WAIT_OBJECT_0:
servicemanager.LogInfoMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
break
else:
main()
if __name__ == '__main__':
if len(sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(TestService)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(TestService)
The execution stops when script starts interacting with the file in the filesystem.
I have the same issue. If it can to help you, you can try to debug it after the installation. It worked for me, but it's not how I should run it.
To do it, start command prompt as administrator, then write these commands
Then you'll see your service running in the prompt.
My problem did not show when I did this, but after installation, I could not start the service from service.msd if I have in my code the method get of configparser, but not only reading data. I think that the problem is about virtual envirovments or privileges, but I did not solve it running it as administrator.
EDIT:
I solved my problem and maybe this could solve your problem too. When you run your program as a service, it run in C:\Windows\System32 , so the current path is not where your python file is stored. When you try to read a config file using configparser, it silently fail and you can't notice that until you try to store the data you read from configuration file. You could try to insert a "try...except" to your code to identify which error stop your service start. If the error is a "NoSection Error", it mean that when you try to use data readed from config file, it failed. You could try to add a print of the current directory in your log, so you can see where the program run, and then move your .ini file in there or try to use an absolute path. NOTE: If you use a dinamically path you could have same issue (that was my problem). If you try to get the user path, you get "C:\Windows\System32\config\systemprofile"
This is an example of what you could implement to solve your problem