20"""Win32 specific microscope classes.
22If called as a program, it will configure and control a Windows
23service to serve devices, similar to the device-server program.
25To configure and run as a Windows service use::
28 [install,remove,update,start,stop,restart,status] \
42# These win32* modules both import win32api which is a pyd file.
43# Importing win32api can be problematic because of Windows things
44# specially when running as a Windows. So if it fails, add the
48 import win32serviceutil
50 os.environ[
"PATH"] +=
";" + os.path.split(sys.executable)[0]
52 import win32serviceutil
56 """Serves microscope devices via a Windows service.
58 Win32 service manipulation relies on fetching _svc_name_ without
59 instantiating any object, so _svc_name_ must be a class
60 attribute. This means that only one MicroscopeService may be
61 installed on any one system,
and will be responsible
for serving
62 all microscope devices on that system.
65 _svc_name_ = "MicroscopeService"
66 _svc_display_name_ =
"Microscope device servers"
67 _svc_description_ =
"Serves microscope devices."
70 def set_config_file(cls, path):
71 win32serviceutil.SetServiceCustomOption(
72 cls.
_svc_name_,
"config", os.path.abspath(path)
76 def get_config_file(cls):
77 return win32serviceutil.GetServiceCustomOption(
81 def log(self, message, error=False):
83 logFunc = servicemanager.LogErrorMsg
85 logFunc = servicemanager.LogInfoMsg
88 def __init__(self, args):
90 win32serviceutil.ServiceFramework.__init__(self, args)
94 configfile = win32serviceutil.GetServiceCustomOption(
97 os.chdir(os.path.dirname(configfile))
98 self.
log(
"Using config file %s." % configfile)
99 self.
log(
"Logging at %s." % os.getcwd())
100 self.ReportServiceStatus(win32service.SERVICE_RUNNING)
108 options = DeviceServerOptions(
109 config_fpath=configfile,
110 logging_level=logging.INFO,
114 devices = validate_devices(configfile)
115 serve_devices(devices, options, self.
stop_event)
116 except Exception
as e:
117 servicemanager.LogErrorMsg(str(e))
120 self.
log(
"Service shutdown complete.")
121 self.ReportServiceStatus(win32service.SERVICE_STOPPED)
124 self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
128def handle_command_line():
129 if len(sys.argv) == 1:
130 print(
"\nNo action specified.\n", file=sys.stderr)
132 if sys.argv[1].lower()
in [
"install",
"update"]:
133 if len(sys.argv) == 2:
134 print(
"\nNo config file specified.\n")
136 configfile = sys.argv.pop()
137 win32serviceutil.HandleCommandLine(MicroscopeWindowsService)
139 MicroscopeWindowsService.set_config_file(configfile)
141 win32serviceutil.HandleCommandLine(MicroscopeWindowsService)
144if __name__ ==
"__main__":
145 handle_command_line()
def log(self, message, error=False)