Hi Thomas,
Your definition of IServiceProvider works perfect for me.
I am happy for it to go in comtypes/__init__.py, but for now though,
again I have attached a servprov.py with your changes, plus
testQueryService.py which is some code that shows how IServiceProvider
can be used.
running testQueryService.py starts Internet Explorer, navigates to
'about:blank', and query interface to IServiceProvider on the body
element, and uses queryService to get to an IAccessible (MSAA) object.
Hope this code will be useful enough to be made in to a testcase.
Mick
On 17/06/2009 5:01 AM, Thomas Heller wrote:
Michael Curran schrieb:
Hi,
Attached is a module which contains a definition of the IServiceProvider
interface. This interface is provided as an interface on COM objects to
make it possible to switch to a different service, related to the
object. For example given an IAccessible (MSAA) object, you can use its
IServiceProvider interface to get to other things such as an
IHTMLElement (when dealing with MSHTML), or IAccessible2 etc.
Info on this interface can be found at:
http://msdn.microsoft.com/en-us/library/cc678965%28VS.85%29.aspx
Generally, the interface seems simple enough (only one method)
and generic enough so that it is justified to add it to the
comtypes\__init__.py module.
It would also be great if you can supply a small code snippet that uses the
IServiceProvider.QueryService method, so that I can make a simple test
for it.
IServiceProvider is defined in servprov.idl in the Microsoft Platform SDK.
A part from providing a standard comtypes definition of the interface, I
have also overridden the QueryService method, to be a little more
pythonic, so that you can pass an interface as the second argument,
rather than just an IID, and then it actually returns an instance of
that interface, rather than just an IUnknown pointer.
I propose that this module (servprov.py) be added to comtypes, so that
others can make use of this, rather than having to code the definition
manually.
Note also that IServiceProvider is not included in any standard type
library that I know of, so defining this interface specifically is the
only way to use it.
Hopefully I have formatted the file suitably for inclusion.
# -*- coding: mbcs -*-
from ctypes import *
from comtypes import *
class IServiceProvider(IUnknown):
_case_insensitive_ = True
_iid_ = GUID('{6D5140C1-7436-11CE-8034-00AA006009FA}')
_idlflags_ = []
I'd suggest to remove the _case_insensitive_ and _idlflags_ attributes.
#Overridden QueryService to make it nicer to use (passing it an interface
and it returns a pointer to that interface)
def QueryService(self,serviceIID,interface):
if not issubclass(interface,IUnknown):
raise ValueError(interface argument must be a COM interface)
interfaceIID=interface._iid_
if not isinstance(serviceIID,GUID):
raise ValueError(serviceIID argument must be a GUID)
p=self._QueryService(byref(serviceIID),byref(interfaceIID))
return POINTER(interface)(p)
I think the issubclass tests can also be omitted.
IServiceProvider._methods_ = [
COMMETHOD([], HRESULT, 'QueryService',
( ['in'], POINTER(GUID), 'guidService' ),
( ['in'], POINTER(GUID), 'riid' ),
( ['out'], POINTER(c_void_p), 'ppvObject' )),
COMMETHOD([], HRESULT, 'RemoteQueryService',
( ['in'], POINTER(GUID), 'guidService' ),
( ['in'], POINTER(GUID), 'riid' ),
( ['out'], POINTER(POINTER(IUnknown)), 'ppvObject' )),
]
The definition for 'RemoteQueryService' must be removed. The IServiceProvider
has only ONE method (the midl-compiler sometimes creates C/C++ wrapper methods
called Remote..., but I guess these have somehow to do with marshalling
or something like that).
All in all, this is how I would write this interface:
class IServiceProvider(IUnknown):
_iid_ = GUID('{6D5140C1-7436-11CE-8034-00AA006009FA}')
# Overridden QueryService to make it nicer to use (passing it an
# interface and it returns a pointer to that interface)
def QueryService(self, serviceIID, interface):
p = POINTER(interface)()
self._QueryService(byref(serviceIID), byref(interface._iid_), byref(p))
return p
_methods_ = [
COMMETHOD([], HRESULT, 'QueryService',
( ['in'], POINTER(GUID), 'guidService' ),
( ['in'], POINTER(GUID), 'riid' ),
( ['in'], POINTER(c_void_p), 'ppvObject' ))
]
Does this work for you?
BTW: The reason that the third parameter must be declared 'in' is that
still 'out' parameters are somewhat broken in comtypes.
# -*- coding: mbcs -*-
from ctypes import *
from comtypes import *
class IServiceProvider(IUnknown):
_iid_ = GUID('{6D5140C1-7436-11CE-8034-00AA006009FA}')
# Overridden QueryService to make it nicer to use (passing it an
# interface and it returns a