Skip to content

Instantly share code, notes, and snippets.

@mgrandi
Last active March 11, 2020 23:14
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mgrandi/0cf9e603135eda176534 to your computer and use it in GitHub Desktop.
Save mgrandi/0cf9e603135eda176534 to your computer and use it in GitHub Desktop.
Example Windows Service, written using asyncio and frozen using cx_Freeze
# for NAME and DISPLAY_NAME, the '%s' is replaced whatever you pass to <service.exe> --install NAMEHERE, so you can
# register the same exe multiple times with different names and configuration files
NAME = 'cx_FreezeSampleService%s' # what the name of the service is, used in command line things like "sc"
DISPLAY_NAME = 'cx_Freeze Sample Service - %s' # display name of the service, this is what you see in the "Services" window
MODULE_NAME = 'service' # python file containing the actual service code
CLASS_NAME = 'Handler' # class name of the service, since it doesn't extend anything, all it needs are certain methods
DESCRIPTION = 'Sample service description' # description of the service, seen in the Service Properties window
AUTO_START = False # does the service auto start?
# does the service respond to session changes? Setting this to True and implemnting SessionChanged(sessionId, eventType)
# is the only way to respond to things like Shutdown. See
# https://msdn.microsoft.com/en-us/library/windows/desktop/ms683241%28v=vs.85%29.aspx for the event types
SESSION_CHANGES = False
2015-02-26 14:56:17,513 - INFO - root|__init__|2532: *******************************************************
2015-02-26 14:56:17,514 - DEBUG - root|__init__|2532: Using proactor: IocpProactor
2015-02-26 14:56:17,518 - INFO - root|Initialize|2532: Initalize() - The configfilename is C:\Users\Mark\base_cxfreeze_example\build\exe.win-amd64-3.4\cx_FreezeSampleService.ini
2015-02-26 14:56:17,518 - INFO - root|Run|2532: Run()
2015-02-26 14:56:17,518 - INFO - root|Run|2532: starting run_until_complete()
2015-02-26 14:56:17,518 - INFO - root|theloop|2532: waiting for event
###########################################################
# NOTE: notice how Stop() was called by a different thread!
# (thread 3132 instead of the main thread, 2532)
###########################################################
2015-02-26 14:56:25,449 - INFO - root|Stop|3132: Stop()
2015-02-26 14:56:25,450 - INFO - root|stoploop|2532: setting stopReuqestedEvent
2015-02-26 14:56:25,450 - INFO - root|theloop|2532: stopRequestedEvent set! setting stopFinishedEvent
2015-02-26 14:56:25,451 - INFO - root|stoploop|2532: stopFinishedEvent is set, shutting down loop
2015-02-26 14:56:25,451 - INFO - root|Run|2532: stopFinishedEvent set, loop completed
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
example service in cx_freeze, using asyncio. This also has logging statements showing
how the flow of the service should go.
"""
import logging
import asyncio
import pathlib
import sys
class Handler(object):
# no parameters are permitted; all configuration should be placed in the
# configuration file and handled in the Initialize() method
def __init__(self):
log_file_path = pathlib.Path(sys.executable).parent.resolve().joinpath("handler_log.log")
logging.basicConfig(level="DEBUG", format="%(asctime)s - %(levelname)s - %(funcName)s: %(message)s",
filename=str(log_file_path))
logging.info("*******************************************************")
# set up instance variables
self.loop = asyncio.ProactorEventLoop()
asyncio.set_event_loop(self.loop)
self.stopRequestedEvent = asyncio.Event(loop=self.loop)
self.stopFinishedEvent = asyncio.Event(loop=self.loop)
# called when the service is starting
def Initialize(self, configFileName):
logging.info("Initalize() - The configfilename is %s", configFileName)
@asyncio.coroutine
def theloop(self):
logging.info("waiting for event")
yield from self.stopRequestedEvent.wait()
logging.info("stopRequestedEvent set! setting stopFinishedEvent")
self.stopFinishedEvent.set()
# called when the service is starting immediately after Initialize()
# use this to perform the work of the service; don't forget to set or check
# for the stop event or the service GUI will not respond to requests to
# stop the service
def Run(self):
logging.info("Run()")
logging.info("starting run_until_complete()")
asyncio.async(self.theloop())
self.loop.run_forever()
logging.info("stopFinishedEvent set, loop completed")
self.loop.shutdown()
logging.info("loop shutdown")
@asyncio.coroutine
def stoploop(self):
logging.info("setting stopReuqestedEvent")
self.stopRequestedEvent.set()
yield from self.stopFinishedEvent.wait()
logging.info("stopFinishedEvent is set, shutting down loop")
self.loop.stop()
# called when the service is being stopped by the service manager GUI
def Stop(self):
logging.info("Stop()")
# make sure that stoploop() runs on the same thread as Run(), since Stop() gets called on
# a different thread other then the 'main one'
self.loop.call_soon_threadsafe(asyncio.async,self.stoploop())
def SessionChanged(self, sessionId, eventType)
# NOT IMPLEMENTED
# needs SESSION_CHANGES set to True in your config.py file
# see https://msdn.microsoft.com/en-us/library/windows/desktop/ms683241%28v=vs.85%29.aspx for the event types
pass
# -*- coding: utf-8 -*-
# A simple setup script for creating a Windows service. See the comments in the
# Config.py and ServiceHandler.py files for more information on how to set this
# up.
#
# Installing the service is done with the option --install <Name> and
# uninstalling the service is done with the option --uninstall <Name>. The
# value for <Name> is intended to differentiate between different invocations
# of the same service code -- for example for accessing different databases or
# using different configuration files.
from cx_Freeze import setup, Executable
options = {
'build_exe': {
'includes': ['service', 'cx_Logging']
}
}
executables = [
Executable('config.py', base='Win32Service',
targetName='cx_FreezeSampleService.exe')
]
setup(name='cx_FreezeSampleService',
version='0.1',
description='Sample cx_Freeze Windows serice',
executables=executables,
options=options
)
@vadv
Copy link

vadv commented Feb 11, 2016

Hello! I have error: 'ImportError: No module name cx_Logging' while using Python2.7 x86 and cx_Freeze 4.3.4 installed via pip.
What version are you using?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment