Microsoft COM and "service" class

jim.vickroy jim.vickroy at noaa.gov
Wed Jul 18 13:49:27 EDT 2001


Hello Mark,

Thanks for your quick response.

BTW, how do you notice these messages so quickly?  Are you using some type of
tool?

Here is a, hopefully, simple example of what I am trying to do.  I hope I did
not introduce any new errors when I made this simplification!

####### begin file com_service.py ###################
import Queue
import win32event

import win32serviceutil
import win32service
import win32event



class component ( win32serviceutil.ServiceFramework ):
 """
 This implementation is really a *Singleton*.
 """


 # MS COM attributes:
 _reg_progid_  = 'Trial.COM.Service'
 _reg_clsid_   = '{78FF80EE-8E81-4816-BD6C-30D5924F2901}' #> must be unique -
obtained via: print pythoncom.CreateGuid()
 _public_methods_ = ['accept', 'backlog']

 # MS Win *service* attributes:
 _svc_name_   = _reg_progid_
 _svc_display_name_ = 'Trial COM service'


 def __init__ ( self, args ) :
  """
  Initializes an instance.
  """

  print '\n\n *** starting: com_service component.__init__ ***\n'  #! debug
  import servicemanager  #! debug
  servicemanager.LogInfoMsg ( 'args: ' + str ( args ) ) #! debug --> args:
(u'SXI.processor_events_log',)
  servicemanager.LogInfoMsg ( 'starting: com_service component.__init__' ) #!
debug

  print '\n\n *** starting: win32serviceutil.ServiceFramework.__init__ ***\n'
#! debug
  servicemanager.LogInfoMsg ( 'starting:
win32serviceutil.ServiceFramework.__init__' ) #! debug
  win32serviceutil.ServiceFramework.__init__(self, args)
  print '\n\n *** completed: win32serviceutil.ServiceFramework.__init__
***\n'  #! debug
  servicemanager.LogInfoMsg ( 'completed:
win32serviceutil.ServiceFramework.__init__' ) #! debug

  # Create a "request stop" event to be set by the SvcStop procedure.
  self._stop_request = win32event.CreateEvent (None, 0, 0, None)

  self._ingest_queue = Queue.Queue ( maxsize = 0 ) # grow to available memory


 # Implementation of the COM interface.


 def accept ( self, item ) :
  """
  Queues an item for processing.
  """

  self._ingest_queue.put ( item )


 def backlog ( self ) :
  """
  Returns the number of items remaining to be processed.
  """

  return self._ingest_queue.qsize()


 # Implementation of the MS OS *services* interface:


 def SvcStop ( self ) :
  """
  Prepares this service to be stopped.
  """

  # First, send an acknowledgement to the SCM.
  self.ReportServiceStatus (win32service.SERVICE_STOP_PENDING)

  # Set the STOP event signal.
  win32event.SetEvent (self._stop_request)


 def SvcDoRun (self):
  """
  Perpetually removes messages from the source queue and ...

  Responds to a STOP request by exiting the perpetual loop and returning.
  """

  # Put: "service started" message in Win Event Log.
  import servicemanager # provided at runtime - can not be at start of module
  servicemanager.LogInfoMsg ( component._svc_display_name_ + ' started')

  while 1: # do-forever

   try:
    message = self._ingest_queue.get ( block = 0 ) # do not wait for a queue
entry
    #! determine target file for message
    #! open target file
    #! copy message to target file
   except Queue.Empty:
    pass # ignore empty queue warning
   except Exception, error_object:
    servicemanager.LogErrorMsg \
     ( component._svc_display_name_ + ' unable to process message - reason: '
+ str (error_object) )

   #! close target file

   # Pause to determine if a STOP-service request has been made; if so exit
this loop.
   result = win32event.WaitForSingleObject (self._stop_request, 1 * 1000) #
milli-secs
   if result == win32event.WAIT_OBJECT_0: break # a request to stop this
service has been received

  # Put: "service stopped" message in Win Event Log.
  servicemanager.LogInfoMsg ( component._svc_display_name_ + ' stopped')


 # Auxillary methods:




if __name__=='__main__':

 # Prepare component to be a MS OS service:
 import win32serviceutil
 win32serviceutil.HandleCommandLine ( component )

 # Prepare component to be a MS COM object:
 import win32com.server.register
 win32com.server.register.UseCommandLine ( component )

####### end file com_service.py ###################



####### begin file test_com.py ###################

import win32com.client

com_obj = win32com.client.Dispatch ('Trial.COM.Service')
print 'queue backlog: ', com_obj.backlog()

####### end file test_com.py ###################



Add here is a sample session on my Win 2k (professional) system using Python
2.0:

D:\applications\sec\sxi>
D:\applications\sec\sxi>com_service.py install
Installing service Trial.COM.Service to Python class
D:\applications\sec\sxi\com_service.component
Service installed
Registered: Trial.COM.Service

D:\applications\sec\sxi>com_service.py start
Starting service Trial.COM.Service
Registered: Trial.COM.Service

D:\applications\sec\sxi>test_com.py
Traceback (most recent call last):
  File "D:\applications\sec\sxi\test_com.py", line 3, in ?
    com_obj = win32com.client.Dispatch ('Trial.COM.Service')
  File "D:\Python20\win32com\client\__init__.py", line 94, in Dispatch
    dispatch, userName =
dynamic._GetGoodDispatchAndUserName(dispatch,userName,clsctx)
  File "D:\Python20\win32com\client\dynamic.py", line 80, in
_GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File "D:\Python20\win32com\client\dynamic.py", line 71, in _GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx,
pythoncom.IID_IDispatch)
pywintypes.com_error: (-2147221231, 'ClassFactory cannot supply requested
class', None, None)

D:\applications\sec\sxi>

Mark Hammond wrote:

> jim.vickroy wrote:
>
> > which I believe is caused by the following statement in my
> > implementation:
> >
> >   win32serviceutil.ServiceFramework.__init__(self, args)
> >
> > I do not understand where and how the 'args' parameter is being defined.
>
> "args" comes from the service control manager.  For "normal" services,
> the service args can be defined in the dialog used to start and stop
> services.
>
> > If I strip the "service" interface (which references the 'args'
> > parameter) from my class, it seems to work just fine as a COM object.
> >
> > Could someone offer some suggestions on what I need to do.
>
> Any chance of a trivial sample I can keep in the win32com test suite?
> This will help me to track it down once and for all.
>
> Mark.




More information about the Python-list mailing list