How to install, start and stop Windows Service using pywin32 with line command options in Python?

55 Views Asked by At

I need to install a service by passing the options --username, --password, --startup and others.

But I can't, I always get the error:

Usage: 'observador.py [options] install|update|remove|start [...]|stop|restart [...]|debug [...]' Options for 'install' and 'update' commands only: --username domain\username : The Username the service is to run under --password password : The password for the username --startup [manual|auto|disabled|delayed] : How the service starts, default = manual --interactive : Allow the service to interact with the desktop. --perfmonini file: .ini file to use for registering performance monitor data
--perfmondll file: .dll file to use when querying the service for performance data, default = perfmondata.dll Options for 'start' and 'stop' commands only: --wait seconds: Wait for the service to actually start or stop. If you specify --wait with the 'stop' option, the service and all dependent services will be stopped, each waiting the specified period.

The file where I implemented the service contains the following code:

import sys
from time import sleep
import win32service  
import win32serviceutil  
import win32event 
import socket
import servicemanager
import os
import logging


class DoAnything():
    TIME_TO_LOOP = 10
       
    def start(self, service:win32serviceutil.ServiceFramework):
        while service.isAlive:
            logging.info("Toc Toc")
            sleep(self.TIME_TO_LOOP)


class PySvc(win32serviceutil.ServiceFramework):  
    _svc_name_ = "Observador"  
    _svc_display_name_ = "Observador"  

    logging.basicConfig(level=logging.DEBUG, filename=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'log.txt'), format="%(asctime)s - %(levelname)s - %(message)s")  

    def __init__(self, args):  
       win32serviceutil.ServiceFramework.__init__(self,args)  
       self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
       self.isAlive = True
       socket.setdefaulttimeout(60)
    
    def SvcStop(self):
       logging.info(f"SCM stop the service")  
       self.isAlive = False 
       self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)  
       win32event.SetEvent(self.hWaitStop) 
    
    def SvcDoRun(self):
        logging.info(f"SCM start the service")  
        self.isAlive = True 
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE, 
                              servicemanager.PYS_SERVICE_STARTED, (self._svc_name_, ''))  

        self.main()  
        win32event.WaitForSingleObject(self.hWaitStop, win32event.INFINITE)

    def main(self):
        DoAnything().start(self)


if __name__ == '__main__':
    if len(sys.argv) == 1:
        servicemanager.Initialize()
        servicemanager.PrepareToHostSingle(PySvc)
        servicemanager.StartServiceCtrlDispatcher()
    else:
        win32serviceutil.HandleCommandLine(PySvc)

And here is the entry point responsible for installing and starting the service:

import sys
import os
import logging
import subprocess
from time import sleep


class Main():
    def __init__(self) -> None:
        self.SCRIPT_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "observador.py")
        self.windows_user = 'User01'
        self.windows_pwd = '123456'
        
    def install_service(self): 
        cmd_install = f"python {self.SCRIPT_PATH} install --username= {self.windows_user} --password ={self.windows_pwd} --startup = auto"  
        self.exec_subprocess(cmd_install)
   
    def start_service(self):
        cmd_start = f"python {self.SCRIPT_PATH} start --wait= 10"
        self.exec_subprocess(cmd_start)

    def exec_subprocess(self, comando):
        try:
            subprocess.run(comando, check=True)
        except subprocess.CalledProcessError as e:
            logging.error(f"Commando Failed: \n {comando} \n {e}")
            sys.exit(1)
    
if __name__ == '__main__':
    main = Main()
    main.install_service()
    sleep(2)
    main.start_service()

If I remove the longs commands the service installs and starts successfully. this is how it works:

cmd_install = f"python {self.SCRIPT_PATH} install"
cmd_start = f"python {self.SCRIPT_PATH} start"

What is the correct way to install and start this service with command lines?

0

There are 0 best solutions below