Finishing samples/python_service.py

This commit is contained in:
hakril
2024-12-31 10:23:08 +01:00
parent 196d4dcac4
commit 99d39604df
5 changed files with 170 additions and 3 deletions
@@ -116,4 +116,28 @@ SERVICE_WIN32_OWN_PROCESS)
#define SERVICE_ACCEPT_SESSIONCHANGE 0x00000080
#define SERVICE_ACCEPT_PRESHUTDOWN 0x00000100
#define SERVICE_ACCEPT_TIMECHANGE 0x00000200
#define SERVICE_ACCEPT_TRIGGEREVENT 0x00000400
#define SERVICE_ACCEPT_TRIGGEREVENT 0x00000400
//
// Service object specific access type
//
#define SERVICE_QUERY_CONFIG 0x0001
#define SERVICE_CHANGE_CONFIG 0x0002
#define SERVICE_QUERY_STATUS 0x0004
#define SERVICE_ENUMERATE_DEPENDENTS 0x0008
#define SERVICE_START 0x0010
#define SERVICE_STOP 0x0020
#define SERVICE_PAUSE_CONTINUE 0x0040
#define SERVICE_INTERROGATE 0x0080
#define SERVICE_USER_DEFINED_CONTROL 0x0100
#define SERVICE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | \
SERVICE_QUERY_CONFIG | \
SERVICE_CHANGE_CONFIG | \
SERVICE_QUERY_STATUS | \
SERVICE_ENUMERATE_DEPENDENTS | \
SERVICE_START | \
SERVICE_STOP | \
SERVICE_PAUSE_CONTINUE | \
SERVICE_INTERROGATE | \
SERVICE_USER_DEFINED_CONTROL)
+12
View File
@@ -922,6 +922,18 @@ Functions
.. function:: StartServiceCtrlDispatcherW(lpServiceStartTable)
.. function:: RegisterServiceCtrlHandlerExA(lpServiceName, lpHandlerProc, lpContext)
.. function:: RegisterServiceCtrlHandlerExW(lpServiceName, lpHandlerProc, lpContext)
.. function:: RegisterServiceCtrlHandlerA(lpServiceName, lpHandlerProc)
.. function:: RegisterServiceCtrlHandlerW(lpServiceName, lpHandlerProc)
.. function:: SetServiceStatus(hServiceStatus, lpServiceStatus)
.. function:: SetServiceBits(hServiceStatus, dwServiceBits, bSetBitsOn, bUpdateImmediately)
.. function:: SetupDiClassNameFromGuidA(ClassGuid, ClassName, ClassNameSize, RequiredSize)
.. function:: SetupDiClassNameFromGuidW(ClassGuid, ClassName, ClassNameSize, RequiredSize)
+4
View File
@@ -511,6 +511,10 @@ Simple types
.. autoclass:: PDNS_QUERY_COMPLETION_ROUTINE
.. autoclass:: LPHANDLER_FUNCTION
.. autoclass:: LPHANDLER_FUNCTION_EX
.. autoclass:: LPCONTEXT
.. autoclass:: HCERTSTORE
+124
View File
@@ -0,0 +1,124 @@
import sys
import os.path
import argparse
import datetime
import ctypes
import windows
import windows.generated_def as gdef
SERVICE_NAME = u"PFW_SERVICE_DEMO"
SERVICE_DESCRIPTION = u"PythonForWindows demo service"
SERVICE_LOGFILE = os.path.join(os.path.dirname(__file__), "logs.txt")
SERVICE_HANDLE = None
def install_demo_service():
path = "{executable} {pyfile} --run".format(executable=sys.executable, pyfile=__file__)
print("Registering service <{0}> as : <{1}>".format(SERVICE_NAME, path))
newservice = windows.system.services.create(
name=SERVICE_NAME,
description=SERVICE_DESCRIPTION,
access=gdef.SERVICE_ALL_ACCESS,
type=gdef.SERVICE_WIN32_OWN_PROCESS,
start=gdef.SERVICE_DEMAND_START,
path=path,
user=None
)
print(newservice)
return
def uninstall_demo_service():
print("Deleting service")
print(windows.system.services[SERVICE_NAME].delete())
def log(s):
with open(SERVICE_LOGFILE, "a") as f:
f.write("[{time}] {s}\n".format(time=datetime.datetime.now(), s=s))
@ctypes.WINFUNCTYPE(gdef.DWORD, gdef.DWORD, gdef.DWORD, gdef.PVOID, gdef.PVOID)
def service_handlerex(dwControl, dwEventType, lpEventData, lpContext):
log("in service_handlerex")
log("service_handlerex: called with {0}".format(dwControl))
if dwControl == gdef.SERVICE_CONTROL_STOP:
log("Stopping the service")
running_status = gdef.SERVICE_STATUS(
dwServiceSpecificExitCode=0,
dwServiceType =gdef.SERVICE_WIN32_OWN_PROCESS,
dwCurrentState=gdef.SERVICE_STOPPED,
dwWin32ExitCode=gdef.NO_ERROR,
dwControlsAccepted=0
)
try:
windows.winproxy.SetServiceStatus(SERVICE_HANDLE, running_status)
except Exception as e:
log(str(e))
return 0
@ctypes.WINFUNCTYPE(gdef.PVOID, gdef.DWORD, ctypes.POINTER(gdef.LPWSTR))
def service_main(dwNumServicesArgs, lpServiceArgVectors):
global SERVICE_HANDLE
log("In service_main")
log("service_main: {0}".format(dwNumServicesArgs))
log("service_main: {0}".format(lpServiceArgVectors[0]))
try:
log("Calling RegisterServiceCtrlHandlerExW")
SERVICE_HANDLE = windows.winproxy.RegisterServiceCtrlHandlerExW(SERVICE_NAME, ctypes.cast(service_handlerex, gdef.PVOID), None)
log("RegisterServiceCtrlHandlerExW handle: {0}".format(SERVICE_HANDLE))
running_status = gdef.SERVICE_STATUS(
dwServiceSpecificExitCode=0,
dwServiceType =gdef.SERVICE_WIN32_OWN_PROCESS,
dwCurrentState=gdef.SERVICE_RUNNING,
dwWin32ExitCode=gdef.NO_ERROR,
dwControlsAccepted=gdef.SERVICE_ACCEPT_STOP | gdef.SERVICE_ACCEPT_PAUSE_CONTINUE
)
res = windows.winproxy.SetServiceStatus(SERVICE_HANDLE, running_status)
log("Service is running : {0}".format(res))
except Exception as e:
log(str(e))
raise
return None
def run_demo_service():
log("start of run_demo_service()")
try:
SERVICE_TABLE = (gdef.SERVICE_TABLE_ENTRYW * 2)(
gdef.SERVICE_TABLE_ENTRYW(SERVICE_NAME, ctypes.cast(service_main, gdef.PVOID)),
gdef.SERVICE_TABLE_ENTRYW(None, None),
)
log("Calling: StartServiceCtrlDispatcherW()")
result = windows.winproxy.StartServiceCtrlDispatcherW(SERVICE_TABLE)
log("StartServiceCtrlDispatcherW returned: {0}".format(result))
log("Quitting")
except Exception as e:
log(str(e))
raise
parser = argparse.ArgumentParser(prog=__file__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--install", action="store_true", help="Install the service in registry")
group.add_argument("--uninstall", action="store_true", help="UnInstall the service in registry")
group.add_argument("--run", action="store_true", help="Called by the services.exe to run the service")
if __name__ == "__main__":
args = parser.parse_args()
if args.install:
install_demo_service()
elif args.uninstall:
uninstall_demo_service()
elif args.run:
log("calling run_demo_service()")
log(sys.argv)
run_demo_service()
else:
raise ValueError("Unknown argument")
+5 -2
View File
@@ -149,7 +149,7 @@ class ServiceManager(utils.AutoHandle):
def enumerate_services(self):
return list(self._enumerate_services_generator())
def create(self, name, description, access, type, start, path):
def create(self, name, description, access, type, start, path, user=None):
newservice_handle = windows.winproxy.CreateServiceW(
self.handle, # hSCManager
name, # lpServiceName
@@ -162,7 +162,7 @@ class ServiceManager(utils.AutoHandle):
None, # lpLoadOrderGroup
None, # lpdwTagId
None, # lpDependencies
None, # lpServiceStartName
user, # lpServiceStartName
None) # lpPassword
return Service(handle=newservice_handle, name=name, description=description)
@@ -238,6 +238,9 @@ class Service(gdef.SC_HANDLE):
windows.winproxy.ControlService(self, gdef.SERVICE_CONTROL_STOP, status)
return status
def delete(self):
return windows.winproxy.DeleteService(self)
def __repr__(self):
return urepr_encode(u"""<{0} "{1}" {2!r}>""".format(type(self).__name__, self.name, self.status.state))