Problem Statement
Creating a Windows service in Python is a common task, often facilitated by numerous code examples available online and tools like Chart GPT. However, a significant challenge arises when attempting to access or start Windows processes within the context of a Windows service. The primary complication stems from the fact that services run under the Local System authority, introducing permission constraints that can hinder the seamless execution of certain tasks.
Introduction
Windows services provide a powerful mechanism for running background tasks that do not require user interaction. In Python, the win32serviceutil
module, part of the pywin32
library, allows developers to create and manage Windows services seamlessly. In this article, we'll explore a Python script that utilizes win32serviceutil
to create a simple Windows service.
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import os
import time
class MyService(win32serviceutil.ServiceFramework):
_svc_name_ = 'MyService'
_svc_display_name_ = 'My Service'
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(120)
self.is_alive = True
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.is_alive = False
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
self.main()
def main(self):
# Main service logic goes here
while self.is_alive:
# Perform your service tasks here
time.sleep(5) # Example: Sleep for 5 seconds
if __name__ == '__main__':
if len(os.sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(MyService)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(MyService)
Understanding the Python Script:
Let's break down the provided Python script, which serves as the foundation for our Windows service.
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import os
import time
These import statements include essential modules such as win32serviceutil
, win32service
, win32event
, servicemanager
, socket
, os
, and time
. These modules collectively provide the necessary tools for creating and managing Windows services.
class MyService(win32serviceutil.ServiceFramework):
_svc_name_ = 'MyService'
_svc_display_name_ = 'My Service'
Here, a class named MyService
is defined, inheriting from win32serviceutil.ServiceFramework
. This class represents our custom Windows service. The _svc_name_
attribute defines the service name, and _svc_display_name_
sets the display name visible in the Windows Services manager.
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
socket.setdefaulttimeout(120)
self.is_alive = True
The __init__
method initializes the service. It creates an event (hWaitStop
) that signals the service to stop when set. The socket.setdefaulttimeout(120)
line sets the default timeout for socket operations, and self.is_alive
tracks whether the service is running.
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
self.is_alive = False
The SvcStop
method is called when the service is stopped. It reports the stop status and signals the hWaitStop
event.
def SvcDoRun(self):
servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
servicemanager.PYS_SERVICE_STARTED,
(self._svc_name_, ''))
self.main()
The SvcDoRun
method is the main entry point for the service. It logs a service start message and calls the main
method.
def main(self):
# Main service logic goes here
while self.is_alive:
# Perform your service tasks here
time.sleep(5) # Example: Sleep for 5 seconds
The main
method contains the core logic of your service. In this example, it includes a loop simulating a service that performs tasks every 5 seconds.
if __name__ == '__main__':
if len(os.sys.argv) == 1:
servicemanager.Initialize()
servicemanager.PrepareToHostSingle(MyService)
servicemanager.StartServiceCtrlDispatcher()
else:
win32serviceutil.HandleCommandLine(MyService)
Finally, the script checks whether it's being run as a standalone application or imported as a module. If run standalone, it initializes and starts the service using servicemanager
.
Conclusion:
This script provides a template for building Windows services in Python using win32serviceutil. Customize the main method to implement your service's specific functionality. In subsequent articles, we'll explore service installation, execution, and management.
Stay tuned for more on mastering Windows services with Python Part II
Top comments (4)
"Finally, the script checks whether it's being run as a standalone application or imported as a module". Really? Isn't it just checking if it is being called with or without a parameter ?
Why is the init needed at all? Doesnt't the base class already do that?
Hi. Help please.
I got error code: pywintypes.error: 1063, 'StartServiceCtrlDispatcher'
How are you Starting you window service please, are you using the below command
python servioce.py install?
Very good. Where can I read Part II?