Skip to main content

A Python package for building Windows services.

Project description

windowsservice

windowsservice is a Python package for building Windows services.

The key features are:

Getting ready

Create and activate a virtual environment:

python -m venv venv
.\venv\Scripts\activate

Installation

Install the windowsservice package from PyPI:

pip install windowsservice

The windowsservice package depends on pywin32 created by Mark Hammond. Installing the windowsservice package also installs the pywin32 dependency.

Coding

  1. Import the BaseService class:

    from windowsservice import BaseService
    
  2. Create a new subclass that inherits from the BaseService class.

  3. Define the following three class variables in the subclass:

    • _svc_name_: A unique identifier for your service.
    • _svc_display_name_: The name shown in the service control manager.
    • _svc_description_: The description shown in the service control manager.

    For example:

    _svc_name_ = "MyWindowsService"
    _svc_display_name_ = "My Windows Service"
    _svc_description_ = "This is my custom Windows service."
    
  4. Override the following methods in the subclass:

    • start(self): This method is invoked when the service starts. Override this to add setup code, such as initializing a running condition.

    • main(self): This method is invoked after start. Override this to create a run loop, typically based on a running condition.

    • stop(self): This method is invoked when the service stops. Override this to add cleanup code, such as releasing resources or to invalidate a running condition.

    For example:

    def start(self):
       self.is_running = True
    
    def main(self):
       while self.is_running:
           time.sleep(5)
    
    def stop(self):
       self.is_running = False
    
  5. Call the parse_command_line class method from the module's entry point. This handles command-line arguments for installing, starting, stopping, and debugging the service.

    For example:

    if __name__ == "__main__":
        ExampleService.parse_command_line()
    

Examples

Basic example (example_service.py):

import time

from windowsservice import BaseService, utils


class ExampleService(BaseService):
    """Example Windows service in Python."""

    _svc_name_ = "PythonExampleWindowsService"
    _svc_display_name_ = "Python Example Windows Service"
    _svc_description_ = "Example Windows service in Python"

    def start(self):
        self.is_running = True

    def main(self):
        while self.is_running:
            utils.log(f"{self._svc_display_name_} is running...")
            time.sleep(5)

    def stop(self):
        self.is_running = False


if __name__ == "__main__":
    ExampleService.parse_command_line()

Example that demonstrates support for multiprocessing (example_service_multiprocessing.py):

import time
from multiprocessing import Process, freeze_support

from windowsservice import BaseService, utils


def stub_server():
    """
    A function that simulates a server process hosted by the Windows service.

    This function logs a message every 5 seconds for a total of 100 times.
    """
    for _ in range(100):
        utils.log("Hello from a process hosted by a Windows service...")
        time.sleep(5)


class ExampleService(BaseService):
    """Example Windows service in Python."""

    _svc_name_ = "PythonExampleWindowsService"
    _svc_display_name_ = "Python Example Windows Service"
    _svc_description_ = "Example Windows service in Python"

    def start(self):
        self.server_process = Process(target=stub_server)

    def main(self):
        self.server_process.start()
        self.server_process.join()

    def stop(self):
        if self.server_process:
            self.server_process.terminate()


if __name__ == "__main__":
    freeze_support()
    ExampleService.parse_command_line()

Usage

Some interactions with a Windows service may require administrative privileges, so you must use an elevated command line interface.

All arguments and options can be listed by invoking the module:

python .\examples\example_service.py
Usage: 'example_service.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.

Install the service

If you want to install the service from the example_service.py example, run:

python .\examples\example_service.py install
Installing service PythonExampleWindowsService
Service installed

You can also choose to install the service so that it will start automatically when Windows starts:

python .\examples\example_service.py --startup=auto install

Start the service

To start/stop the service you can now use the service control manager.

Or, from the command line interface, you can run:

python .\examples\example_service.py start

To start the service in debug mode, run:

python .\examples\example_service.py debug

To verify that the service is working, make sure it is running, and then look into the Windows Event Viewer or, if it is running in debug mode, look at the standard output stream. You should see a message every 5 seconds.

Remove the service

To remove the service, run:

python .\examples\example_service.py remove

PyInstaller

To bundle the service into a convenient standalone executable, you can use PyInstaller.

Install PyInstaller

Install PyInstaller inside your activated virtual environment:

pip install pyinstaller

Create executable

To create a standalone (one-file) executable, use the pyinstaller command:

pyinstaller .\examples\example_service.py --clean --noupx --onefile --noconfirm --hidden-import=win32timezone

The resulting example_service.exe executable can be found in the .\dist directory.

You can use this executable with the same arguments and options as discussed above. For example, to install the service, run:

.\dist\example_service.exe install

You can also create a one-folder bundle. Because the executable does not have to be unpacked first in a temporary location, this has the advantage of making the service start faster.

pyinstaller .\examples\example_service.py --clean --noupx --onedir --noconfirm --hidden-import=win32timezone

In this case, the resulting executable can be found in the dist\example_service directory.

Acknowledgement

This package utilizes the pywin32 library, a collection of Python extensions for Windows. The maintenance and development of this library is credited to Mark Hammond and others in the Python community. Their contributions enable the development of Windows services in Python. Please note that the windowsservice package does not aim to replace pywin32 or win32serviceutil.ServiceFramework, it's just here to make it a little bit easier to use.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

windowsservice-2.0.0.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

windowsservice-2.0.0-py3-none-any.whl (7.0 kB view details)

Uploaded Python 3

File details

Details for the file windowsservice-2.0.0.tar.gz.

File metadata

  • Download URL: windowsservice-2.0.0.tar.gz
  • Upload date:
  • Size: 8.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for windowsservice-2.0.0.tar.gz
Algorithm Hash digest
SHA256 6a83d025f0afbc33740a172fefd1f4a833a6fe3287ec17f3a205f23dbc2fecc3
MD5 fb061a64d79e584b322e630de11c5e6b
BLAKE2b-256 608e3b4feda542c85e95e9e6d03e212336c64c75c7ced3000e14a16b1225954a

See more details on using hashes here.

File details

Details for the file windowsservice-2.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for windowsservice-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 be812a4c0f19fa508175f51964ee8f56bcc27059a6a7ccffac75de55d2848012
MD5 7de819e53fc5d5ffb13da4263cbc38d6
BLAKE2b-256 627c3a01ef7b0e13f593fd42877c7e1f4f039a6d7dcb525a41929b1fbd514381

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page