15

I'm trying to write a windows Service in python, but the tricky part is i want to deploy it on a machine that doesn't have python. I've successfully created a service like this, and it works if i run from my machine. the problem starts when i try to convert it to an exe and then try to install it. first i tried to use cx_freeze service example, (seen here), the setup.py look like this :

from cx_Freeze import setup, Executable

options = {'build_exe': {'includes': ['ServiceHandler']}}

executables = [Executable('Config.py', base='Win32Service', targetName='gsr.exe')]

setup(name='GSR',
    version='0.1',
    description='GSR SERVICE',
    executables=executables,
    options=options
    )

and config.py is:

NAME = 'GSR_%s'
DISPLAY_NAME = 'GSR TEST - %s'
MODULE_NAME = 'ServiceHandler'
CLASS_NAME = 'Handler'
DESCRIPTION = 'Sample service description'
AUTO_START = True
SESSION_CHANGES = False

but when i try to build it (python setup.py build) i get an error: "cx_Freeze.freezer.ConfigError: no base named Win32Service"

Second, i tried using a regular cx_freeze setup, the exe i get installs the service fine but once i try to start it i get an error: "Error 1053: The service did not respond to the start or control request in a timely fashion"

setup.py - python 3.3 regualr exe, installs the service but when trying to start it sends an error:

from cx_Freeze import setup, Executable

packages = ['win32serviceutil','win32service','win32event','servicemanager','socket','win32timezone','cx_Logging','ServiceHandler']
build_exe_options = {"packages": packages}
executable = [Executable("ServiceHandler.py")]


setup(  name = "GSR_test",
        version = "1.0",
        description = "GSR test service",
        options = {"build_exe": build_exe_options},
        executables = executable)

finally, I managed to get it to work in python 2.7 using py2exe, but py2exe isn't available for python 3.3 and I my code is in 3.3

i guess the problem is in the configuration of the setup.py im using with cx_freeze. any ideas ??

my ServiceHandler:

import pythoncom
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
from test import test
import threading

class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "GSR_test"
    _svc_display_name_ = "GSR test Service"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)
        socket.setdefaulttimeout(60)
        self.app = test()
        self.flag = threading.Event()

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)
        self.flag.set()

    def SvcDoRun(self):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,''))
        self.main()

    def main(self):
        t = threading.Thread(target=self.app.run)
        t.start()
        self.flag.wait()
        raise SystemExit

if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)

Setup.py , python 2.7 using py2exe that works: (taken from here)

from distutils.core import setup
import py2exe

setup(  service = ["ServiceHandler"],
        description = "SERVICE TEST",
        modules = ["GSR_test"],
        cmdline_style='pywin32', ) 

Thanks, Amit

4
  • What doesn't work? Are there any errors logged? Commented Feb 23, 2014 at 9:39
  • I updated the question and included more details Commented Feb 24, 2014 at 12:13
  • 2
    The Win32service base only supports Python 2 at the moment. It's waiting for someone to add Python 3 support. Commented Feb 24, 2014 at 22:59
  • No. it's as Thomas K said, the wind32service base in not compatible with python 3 last time I checked. The file is available in c but adjustments need to be made from python 2 to 3 AFAK. I ended up still using python 2.7. If you find a solution, please share :) Commented Jul 20, 2015 at 18:12

3 Answers 3

14

tldr Python 3.5 Windows Service build with pyinstaller : gist

Here a simple Windows Service with python :

WindowsService.py

import servicemanager
import socket
import sys
import win32event
import win32service
import win32serviceutil


class TestService(win32serviceutil.ServiceFramework):
    _svc_name_ = "TestService"
    _svc_display_name_ = "Test Service"

    def __init__(self, args):
        win32serviceutil.ServiceFramework.__init__(self, args)
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        socket.setdefaulttimeout(60)

    def SvcStop(self):
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
        win32event.SetEvent(self.hWaitStop)

    def SvcDoRun(self):
        rc = None
        while rc != win32event.WAIT_OBJECT_0:
            with open('C:\\TestService.log', 'a') as f:
                f.write('test service running...\n')
            rc = win32event.WaitForSingleObject(self.hWaitStop, 5000)


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

Create an exe with pyinstaller (pip install pyinstaller) and python 3.5 :

(env)$ python -V
Python 3.5.2

(env)$ pip freeze
PyInstaller==3.2

(env)$ pyinstaller -F --hidden-import=win32timezone WindowsService.py

Install and run the service

(env) dist\WindowsService.exe install
Installing service TestService
Service installed

(env) dist\WindowsService.exe start
Starting service TestService

Check C:\\TestService.log file.

Stop and clean

(env) dist\WindowsService.exe stop
(env) dist\WindowsService.exe remove
Sign up to request clarification or add additional context in comments.

2 Comments

It really works! Thank you! (Python 3.6.3, PyInstaller==3.3)
How is TestService linked to the main application script?
1

It appears Win32Service was updated with Python 3.x support within the cx_Freeze project as a result of this thread. This user originally had the same issue you reported, so I'm assuming this will also resolve your issue.

Based on the error reported, it's caused when _GetBaseFileName() within Freezer.py fails to find the compiled Win32Service.exe. This executable should be built when cx_Freeze gets built/installed.

If it's not too much to ask, can search the installed cx_Freeze installation directory for "Win32Service.exe" and confirm that it exists. Hopefully this gets you one step closer.

2 Comments

While the base file seems to be updated if i try to freeze a service (using the provided example from cx_freeze) i'm still getting an error - cx_Freeze.freezer.ConfigError: no base named Win32Service. and indeed if I go and look at the bases folder (with the exe not the c file) it's still missing (no win32Service.exe).. maybe it just need to be compiled and someone fortgot. Using cx_freeze v4.3.4
FYI a regular pip install of cx_Freeze won't have the cx_Logging folder in the folder above it, so the Win32Service base will not be compiled. If you download the source to both (to /tmp/cx_Freeze/ and /tmp/cx_Logging) then run python setup.py install on cx_Logging THEN cx_Freeze, you'll end up with the Win32Service base.
1

I've edited the Win32Service.c in the cx_freeze src for python3 support

Edited it with some preprocessor commands, for python2 support too (but not tested for python2 yet)

  1. download sources of cx_freeze from pypi and extract it
  2. download cx_logging and extract it to the cx_freeze-4.3.4 directory
  3. replace the Win32Service.c file in cx_Freeze-4.3.4\source\bases with my edited version
  4. edit line 170 in setup.py from if moduleInfo is not None and sys.version_info[:2] < (3, 0): to if moduleInfo is not None:
  5. run python setup.py build in cx_freeze-4.3.4 directory (you must have MSC installed to compile the C source files)
  6. copy cx_Freeze-4.3.4\build\lib.win32-3.4\cx_Freeze\bases\Win32Service.exe to C:\Python34\Lib\site-packages\cx_Freeze\bases (or the path where your python3 is installed)
  7. now you can create frozen exe with the Win32Service base (no more the cx_Freeze.freezer.ConfigError: no base named Win32Service error)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.