Cody DeGhetto
Cody DeGhetto

Reputation: 193

Python Windows service

I am working on using the Windows API to build a service. I have already tested and used the win32serviceutil.ServiceFramework module yet I am trying to get around using a 3rd party import.

I have the following so far:

LPSERVICE_MAIN_FUNCTIONW = ctypes.WINFUNCTYPE(ctypes.c_ulong, ctypes.c_wchar_p)

class SERVICE_TABLE_ENTRYW(ctypes.Structure):
    _fields_ = [('ServiceName', ctypes.c_wchar_p),
                ('ServiceProc', LPSERVICE_MAIN_FUNCTIONW)]

def test():
    logging.info('Test is running')

service_process = LPSERVICE_MAIN_FUNCTIONW(test)
service_table = SERVICE_TABLE_ENTRYW(ServiceName='Test_Service', ServiceProc=service_process)
ctypes.windll.advapi32.StartServiceCtrlDispatcherW(service_table)

However when calling StartServiceCtrlDispatcherW I get the following error back:

ValueError: Procedure probably called with too many arguments

If anyone could provide some assistance or direction it would be greatly appreciated

Upvotes: 1

Views: 271

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177901

The LPSERVICE_MAIN_FUNCTIONW callback is defined as:

typedef VOID (WINAPI *LPSERVICE_MAIN_FUNCTIONW)(
    DWORD   dwNumServicesArgs,
    LPWSTR  *lpServiceArgVectors
    );

Which is:

LPSERVICE_MAIN_FUNCTIONW = ctypes.WINFUNCTYPE(None, ctypes.c_ulong, ctypes.POINTER(ctypes.c_wchar_p))

or if using ctypes.wintypes:

from ctypes import WINFUNCTYPE,POINTER
from ctypes import wintypes as w

LPSERVICE_MAIN_FUNCTIONW = WINFUNCTYPE(None, w.DWORD, POINTER(w.LPWSTR))

Note the first parameter to WINFUNCTYPE is the return type and the second parameter to the callback is a LPWSTR* not a LPWSTR.

Upvotes: 2

Related Questions