[python-win32] Calling an OLE Automation (IDispatch) server which uses "out params"

Dave Calkins dave at kinematics.com
Thu Dec 13 01:36:53 CET 2012


I'd like to be able to call an OLE Automation (IDispatch) server from 
python to automate an existing application.  I'm not at liberty to 
change the existing automation interface provided by the application so 
I need to get it to work with what the app currently exposes.

The interface I'm attempting to work with makes use of "out params".  
Here's an excerpt from the IDL for a small sample app I created to 
reproduce the issue.

==========
     dispinterface IMyApp
     {
         properties:

         methods:
             [id(1)] void ShowMessage(BSTR msg);
             [id(2)] void SetSettingValue(BSTR settingName, BSTR 
settingValue);
             [id(3)] void GetSettingValue(BSTR settingName, BSTR* 
settingValue);
     };
==========

The first two methods are straightforward and I had no problem calling 
them from python.  The problem is the third one, GetSettingValue, since 
it requires you to pass in a reference to a variable which it then fills 
in for you.

I read through CH12 of "Python Programming on Win32" by Hammond/Robinson 
as a guide.  Based on that I installed pywin32 and then tried running 
MakePy.  Here's an excerpt of the code generated by MakePy.

==========
     def GetSettingValue(self, settingName=defaultNamedNotOptArg, 
settingValue=defaultNamedNotOptArg):
         return self._oleobj_.InvokeTypes(3, LCID, 1, (24, 0), ((8, 0), 
(16392, 0)),settingName
             , settingValue)

     def SetSettingValue(self, settingName=defaultNamedNotOptArg, 
settingValue=defaultNamedNotOptArg):
         return self._oleobj_.InvokeTypes(2, LCID, 1, (24, 0), ((8, 0), 
(8, 0)),settingName
             , settingValue)

     def ShowMessage(self, msg=defaultNamedNotOptArg):
         return self._oleobj_.InvokeTypes(1, LCID, 1, (24, 0), ((8, 0),),msg
             )
==========

Comparing what it generated for GetSettingValue vs. SetSettingValue I 
noted the difference of 16392 vs. 8.  Looking up those in the windows 
headers it appears those numeric constants correspond to 
VT_BYREF|VT_BSTR vs. VT_BSTR.  So MakePy is generating something 
different for the "out param" and it seems to even be noticing that its 
by reference.

I haven't figured out how to actually call this, though.  In CH12 of the 
book I mentioned, it is noted that for such methods the params are 
converted to return values instead.  The example given in the book is:

==========
ok = GetSize( &left, &right, &top, &bottom);
      becomes
left, right, top, bottom = GetSize()
==========

It doesn't appear that this is happening with the MakePy results I'm 
getting.  But clearly MakePy is detecting the "by reference" parameter.

Here's the output I get when attempting to call this method.  I just 
sort of guessed at how I might call that method.

==========
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit 
(Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
 >>> import win32com.client
 >>> x = win32com.client.Dispatch("MyApp.Application")
 >>> x.ShowMessage("Hello, world")
 >>> x.SetSettingValue("sName","sValue")
 >>> sValue = ""
 >>> x.GetSettingValue("sName",sValue)
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<COMObject MyApp.Application>", line 2, in GetSettingValue
pywintypes.com_error: (-2147352571, 'Type mismatch.', None, 2)
 >>> sValue = x.GetSettingName("sName")
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File 
"C:\Users\dave\apps\Python273\lib\site-packages\win32com\client\dynamic.py", 
line 522, in __getattr__
     raise AttributeError("%s.%s" % (self._username_, attr))
AttributeError: MyApp.Application.GetSettingName
 >>>
==========

Any advice on how I can make use of this method, which takes "out 
params", from python?



More information about the python-win32 mailing list