win32service (wxpython) -- i cannot install service

kkt49 kangtae49 at gmail.com
Mon Sep 11 00:13:47 EDT 2006


# vim: et sw=4 ts=8 sts

from wxPython.wx import *
import sys, os, time
import pywintypes
import win32serviceutil
import win32service
import win32event
import win32process

ID_ABOUT = 101
ID_EXIT = 102

# the max seconds we're allowed to spend backing off
BACKOFF_MAX = 300
# if the process runs successfully for more than BACKOFF_CLEAR_TIME
# seconds, we reset the backoff stats to their initial values
BACKOFF_CLEAR_TIME = 30
# the initial backoff interval (the amount of time we wait to restart
# a dead process)
BACKOFF_INITIAL_INTERVAL = 5

class Service(win32serviceutil.ServiceFramework):
    """ A class representing a Windows NT service that can manage an
    instance-home-based Zope/ZEO/ZRS processes """

    # The comment below is mostly irrelevant if you're running a
standalone
    # SchoolBell server, I think. -TEH

    # The PythonService model requires that an actual on-disk class
declaration
    # represent a single service.  Thus, the below definition of
start_cmd,
    # must be overridden in a subclass in a file within the instance
home for
    # each instance.  The below-defined start_cmd (and
_svc_display_name_
    # and _svc_name_) are just examples.

    # To use this script with SchoolTool, just replace "SchoolBell"
    # with "SchoolTool" in the variables below.
    # You'll also need to change 'Python24' to 'Python23' if that's
    # what you've got.  -TEH

    #cmd_str = os.environ["moin_service"]

    #_svc_name_ = r'moin_service'
    #_svc_display_name_ = r'moin_service'
    #start_cmd = r"c:\mmde\moin.exe"
    info = ['', '', '']

    def __init__(self):
        self._svc_name = info[0]
        self._svc_display_name_ = info[1]
        self.start_cmd = info[2]

        win32serviceutil.ServiceFramework.__init__(self)

        # Create an event which we will use to wait on.
        # The "service stop" request will set this event.
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.redirectOutput()

    def __init__(self, args):
        self._svc_name = info[0]
        self._svc_display_name_ = info[1]
        self.start_cmd = info[2]

        win32serviceutil.ServiceFramework.__init__(self, args)
        # Create an event which we will use to wait on.
        # The "service stop" request will set this event.
        self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
        self.redirectOutput()

    def redirectOutput(self):
        #pass
        sys.stdout.close()
        sys.stderr.close()
        sys.stdout = NullOutput()
        sys.stderr = NullOutput()

    def SvcStop(self):
        # Before we do anything, tell the SCM we are starting the stop
process.
        self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)

        # TODO:  This TerminateProcess call doesn't make much sense:
it's
        # doing a hard kill _first_, never giving the process a chance
to
        # shut down cleanly.  Compare to current Zope2 service code,
which
        # uses Windows events to give the process a chance to shut down
        # cleanly, doing a hard kill only if that doesn't succeed.

        # stop the process if necessary
        try:
            win32process.TerminateProcess(self.hZope, 0)
        except pywintypes.error:
            # the process may already have been terminated
            pass
        # And set my event.
        win32event.SetEvent(self.hWaitStop)

    # SvcStop only gets triggered when the user explictly stops (or
restarts)
    # the service.  To shut the service down cleanly when Windows is
shutting
    # down, we also need to hook SvcShutdown.
    SvcShutdown = SvcStop

    def createProcess(self, cmd):
        return win32process.CreateProcess(
            None, cmd, None, None, 0, 0, None, None,
            win32process.STARTUPINFO())

    def SvcDoRun(self):
        # indicate to Zope that the process is daemon managed
(restartable)
        # os.environ['ZMANAGED'] = '1'

        # daemon behavior:  we want to to restart the process if it
        # dies, but if it dies too many times, we need to give up.

        # we use a simple backoff algorithm to determine whether
        # we should try to restart a dead process:  for each
        # time the process dies unexpectedly, we wait some number of
        # seconds to restart it, as determined by the backoff interval,
        # which doubles each time the process dies.  if we exceed
        # BACKOFF_MAX seconds in cumulative backoff time, we give up.
        # at any time if we successfully run the process for more thab
        # BACKOFF_CLEAR_TIME seconds, the backoff stats are reset.

        # the initial number of seconds between process start attempts
        backoff_interval = BACKOFF_INITIAL_INTERVAL
        # the cumulative backoff seconds counter
        backoff_cumulative = 0

        import servicemanager

        # log a service started message
        servicemanager.LogMsg(
            servicemanager.EVENTLOG_INFORMATION_TYPE,
            servicemanager.PYS_SERVICE_STARTED,
            (self._svc_name_, ' (%s)' % self._svc_display_name_))

        while 1:
            start_time = time.time()
            info = self.createProcess(self.start_cmd)
            self.hZope = info[0] # the pid
            if backoff_interval > BACKOFF_INITIAL_INTERVAL:
                # if we're in a backoff state, log a message about
                # starting a new process
                servicemanager.LogInfoMsg(
                    '%s (%s): recovering from died process, new process
'
                    'started' % (self._svc_name_,
self._svc_display_name_)
                    )
            rc = win32event.WaitForMultipleObjects(
                (self.hWaitStop, self.hZope), 0, win32event.INFINITE)
            if rc == win32event.WAIT_OBJECT_0:
                # user sent a stop service request
                self.SvcStop()
                break
            else:
                # user did not send a service stop request, but
                # the process died; this may be an error condition
                status = win32process.GetExitCodeProcess(self.hZope)
                if status == 0:
                    # the user shut the process down from the web
                    # interface (or it otherwise exited cleanly)
                    break
                else:
                    # this was an abormal shutdown.  if we can, we want
to
                    # restart the process but if it seems hopeless,
                    # don't restart an infinite number of times.
                    if backoff_cumulative > BACKOFF_MAX:
                        # it's hopeless
                        servicemanager.LogErrorMsg(
                          '%s (%s): process could not be restarted due
to max '
                          'restart attempts exceeded' % (
                            self._svc_display_name_, self._svc_name_
                          ))
                        self.SvcStop()
                        break
                    servicemanager.LogWarningMsg(
                       '%s (%s): process died unexpectedly.  Will
attempt '
                       'restart after %s seconds.' % (
                            self._svc_name_, self._svc_display_name_,
                            backoff_interval
                            )
                       )
                    # if BACKOFF_CLEAR_TIME seconds have elapsed since
we last
                    # started the process, reset the backoff interval
                    # and the cumulative backoff time to their original
                    # states
                    if time.time() - start_time > BACKOFF_CLEAR_TIME:
                        backoff_interval = BACKOFF_INITIAL_INTERVAL
                        backoff_cumulative = 0
                    # we sleep for the backoff interval.  since this is
async
                    # code, it would be better done by sending and
                    # catching a timed event (a service
                    # stop request will need to wait for us to stop
sleeping),
                    # but this works well enough for me.
                    time.sleep(backoff_interval)
                    # update backoff_cumulative with the time we spent
                    # backing off.
                    backoff_cumulative = backoff_cumulative +
backoff_interval
                    # bump the backoff interval up by 2* the last
interval
                    backoff_interval = backoff_interval * 2

                    # loop and try to restart the process

        # log a service stopped message
        servicemanager.LogMsg(
            servicemanager.EVENTLOG_INFORMATION_TYPE,
            servicemanager.PYS_SERVICE_STOPPED,
            (self._svc_name_, ' (%s) ' % self._svc_display_name_))

class NullOutput:
    """A stdout / stderr replacement that discards everything."""

    def noop(self, *args, **kw):
        pass

    write = writelines = close = seek = flush = truncate = noop

    def __iter__(self):
        return self

    def next(self):
        raise StopIteration

    def isatty(self):
        return False

    def tell(self):
        return 0

    def read(self, *args, **kw):
        return ''

    readline = read

    def readlines(self, *args, **kw):
        return []


class MyFrame(wxFrame):
    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title, wxDefaultPosition,
wxSize(200, 150))
        self.CreateStatusBar()
        self.SetStatusText("This is the statusbar")

        menu = wxMenu()
        menu.Append(ID_ABOUT, "&About", "More information about this
program")
        menu.AppendSeparator()
        menu.Append(ID_EXIT, "E&xit", "Terminate the program")

        menuBar = wxMenuBar()
        menuBar.Append(menu, "&File");

        self.SetMenuBar(menuBar)

        # 서비스명
        servicenameText = wxStaticText(self, -1, "Service Name")
        self.servicenameCtrl = wxTextCtrl(self, -1, size=(200, -1))
        # 서비스로 실행할 명령
        cmdText = wxStaticText(self, -1, "Service command")
        self.cmdCtrl = wxTextCtrl(self, -1, size=(200, -1))
        # 실행 버튼
        installButton = wxButton(self, -1, label="Install", size=(80,
-1))
        removeButton = wxButton(self, -1, label="Remove", size=(80,
-1))
        startButton = wxButton(self, -1, label="Start", size=(80, -1))
        stopButton = wxButton(self, -1, label="Stop", size=(80, -1))
        installButton.Bind(EVT_BUTTON, self.onInstallButtonClick)
        removeButton.Bind(EVT_BUTTON, self.onRemoveButtonClick)
        startButton.Bind(EVT_BUTTON, self.onStartButtonClick)
        stopButton.Bind(EVT_BUTTON, self.onStopButtonClick)

        # Sizer 구성
        sizer = wxFlexGridSizer(rows=2, cols=2, hgap=10, vgap=5)
        sizer.Add(servicenameText) # (0, 0)
        sizer.Add(self.servicenameCtrl) # (0, 1)
        sizer.Add(cmdText) # (1, 0)
        sizer.Add(self.cmdCtrl) # (1, 1)
        sizer.Add(installButton) # (2, 0)
        sizer.Add(removeButton) # (2, 1)
        sizer.Add(startButton) # (3, 0)
        sizer.Add(stopButton) # (3, 1)

        border = wxBoxSizer()
        border.Add(sizer, 0, wxALL, 10)
        self.SetSizerAndFit(border)
        self.Fit()

    def onInstallButtonClick(self, event):
        Service.info[0] = self.servicenameCtrl.GetValue()
        Service.info[1] = self.servicenameCtrl.GetValue()
        Service.info[2] = self.cmdCtrl.GetValue()

        #Service._svc_name_ = self.servicenameCtrl.GetValue()
        #Service._svc_display_name_ = self.servicenameCtrl.GetValue()
        #Service.start_cmd = self.cmdCtrl.GetValue()

        #win32serviceutil.HandleCommandLine(Service)
        win32serviceutil.InstallService(
                win32serviceutil.GetServiceClassString(Service),
                self.servicenameCtrl.GetValue(),
                self.servicenameCtrl.GetValue()
                )


    def onRemoveButtonClick(self, event):
        win32serviceutil.RemoveService(self.servicenameCtrl.GetValue())

    def onStartButtonClick(self, event):
        win32serviceutil.StartService(self.servicenameCtrl.GetValue())

    def onStopButtonClick(self, event):
        win32serviceutil.StopService(self.servicenameCtrl.GetValue())

    #def onOkButtonClick(self, event):
    #    Service._svc_name_ = self.servicenameCtrl.GetValue()
    #    Service._svc_display_name_ = self.servicenameCtrl.GetValue()
    #    Service.start_cmd = (self.cmdCtrl.GetValue())
    #    sys.argv.append(self.argsCtrl.GetValue())
    #    win32serviceutil.HandleCommandLine(Service)


class MyApp(wxApp):
    def OnInit(self):
        frame = MyFrame(NULL, -1, "Hello from wxPython")
        frame.servicenameCtrl.SetValue(r"moin_service")
        frame.cmdCtrl.SetValue(r"c:\mmde\moin.exe")
        #frame.argsCtrl.SetValue("stop")
        Service.info[0] =
frame.servicenameCtrl.SetValue(r"moin_service")
        Service.info[1] =
frame.servicenameCtrl.SetValue(r"moin_service")
        Service.info[2] = frame.cmdCtrl.SetValue(r"c:\mmde\moin.exe")


        frame.Show(true)
        self.SetTopWindow(frame)
        return true

if __name__ == '__main__':
    app = MyApp(0)
    app.MainLoop()

----------------------------
start stop remove ==> ok
I cann't install service

help!!!




More information about the Python-list mailing list