Last active
March 11, 2020 23:14
-
-
Save mgrandi/0cf9e603135eda176534 to your computer and use it in GitHub Desktop.
Example Windows Service, written using asyncio and frozen using cx_Freeze
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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 | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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?