cpede
2014-09-27 22:36:32 UTC
I'm trying to call a COM Interface using Python Script.
I got the installation of Python from ActivePython, and I'm trying to script
parts of my code using the Script Engine. This normally works with VBScript
and JScript, but now I want to extend this with PythonScript.
The Script Engine is called through a COM interface that I have defined. It
seems that most things works, but when I call a method with both a Set and
Get defined, Python fails to locate the correct version of the method.
In my ODL file I have defined a method called Property, which has a propget
and propput flag, with the same name and id, like this:
[propget,id(100)] HRESULT Property([in]BSTR* name,[out,retval]VARIANT* val);
[propput,id(100)] HRESULT Property([in]BSTR* name,[in]VARIANT val);
When called from JScript I can do like this:
Session.Property("Test",2);
In the Scripting Engine "oledisp1.cpp" in COleDispatchImpl::Invoke line
1309, this call is interpret as a DISPATCH_METHOD method, and then corrected
to DISPATCH_PROPERTYPUTREF, based on a test on the arguments in this part of
the code:
// treat member calls on properties just like property get/set
if ((wFlags == DISPATCH_METHOD) &&
((pEntry->pfn == NULL && pEntry->pfnSet == NULL) ||
(pEntry->pfn == NULL && pEntry->pfnSet != NULL) ||
(pEntry->pfn != NULL && pEntry->pfnSet != NULL)))
{
// the entry describes a property but a method call is being
// attempted -- change it to a property get/set based on the
// number of parameters being passed.
wFlags &= ~DISPATCH_METHOD;
UINT nExpectedArgs = pEntry->lpszParams != NULL ?
(UINT)lstrlenA(pEntry->lpszParams) : 0;
if (pDispParams->cArgs <= nExpectedArgs)
{
// no extra param -- so treat as property get
wFlags |= DISPATCH_PROPERTYGET;
}
else
{
// extra params -- treat as property set
wFlags |= DISPATCH_PROPERTYPUTREF;
pDispParams->cNamedArgs = 1;
}
}
When the same method is called from Python, the COleDispatchImpl::Invoke is
initially called with the flag DISPATCH_PROPERTYGET.
This is of cause wrong, since the call must be interpret as a
DISPATCH_PROPERTYPUTREF, then the method call fails with wrong number of
arguments.
Why are Python Script misinterpreting this method call?
Is Python Script not able to handle propget and propput methods as defined
in the OLD file?
Can I in the call to the method in Python Script somehow tell that it is the
propput version of the method I want to call?
Update 1
The above code calls the following macro:
DISP_PROPERTY_PARAM_ID(CMyScriptingObject,"Property",100,GetProperty,SetProp
erty,VT_VARIANT,VTS_BSTR)
Here a Set and a Get (in this case SetProperty and GetProperty) methods are
created. I now found out, that if I implicitly calls the SetProperty method,
it works:
Session.SetProperty("Test",2)
Intuitively I would then expect that GetProperty would work like this:
myProp = Session.GetProperty("Test")
However this calls fails with the following error:
[13:32:49] Python Test
[13:32:52] Scripting
Python ActiveX Scripting Engine
Error: Traceback (most recent call last):
File "<Script Block >", line 20, in <module>
myProp = Session.GetProperty("Test")
File "C:\Python27\lib\site-
packages\win32comext\axscript\client\pyscript.py", line 105, in __getattr__
return getattr(self._scriptItem_.dispatchContainer,attr)
File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line
522, in __getattr__
raise AttributeError("%s.%s" % (self._username_, attr))
AttributeError: Session.GetProperty
In line 20 At column -1 Error Code: 0
Source line: myProp = Session.GetProperty("Test")
It must be related to multiple arguments. However it could also be that I
don't understand the syntax of Python compared to the simpler VBScript.
Update 2
Ok, now I used the PythonWin program to load the tool COM Makepy Utility on
the registered tlb of my COM object. Here I can see:
# The method Property is actually a property, but must be used as a method
to correctly pass the arguments
def Property(self, name=defaultNamedNotOptArg, val=pythoncom.Missing):
return self._ApplyTypes_(100, 2, (3, 0), ((8, 1), (16396, 10)),
u'Property', None,name
, val)
# The method SetProperty is actually a property, but must be used as a
method to correctly pass the arguments
def SetProperty(self, name=defaultNamedNotOptArg,
val=defaultNamedNotOptArg):
return self._oleobj_.InvokeTypes(100, LCID, 4, (3, 0), ((8, 1), (12,
1)),name
, val)
So, I guess that this is why I need to call SetProperty and why GetProperty
does not exist. But the Property exist, but how do I call it?
-cpede
I got the installation of Python from ActivePython, and I'm trying to script
parts of my code using the Script Engine. This normally works with VBScript
and JScript, but now I want to extend this with PythonScript.
The Script Engine is called through a COM interface that I have defined. It
seems that most things works, but when I call a method with both a Set and
Get defined, Python fails to locate the correct version of the method.
In my ODL file I have defined a method called Property, which has a propget
and propput flag, with the same name and id, like this:
[propget,id(100)] HRESULT Property([in]BSTR* name,[out,retval]VARIANT* val);
[propput,id(100)] HRESULT Property([in]BSTR* name,[in]VARIANT val);
When called from JScript I can do like this:
Session.Property("Test",2);
In the Scripting Engine "oledisp1.cpp" in COleDispatchImpl::Invoke line
1309, this call is interpret as a DISPATCH_METHOD method, and then corrected
to DISPATCH_PROPERTYPUTREF, based on a test on the arguments in this part of
the code:
// treat member calls on properties just like property get/set
if ((wFlags == DISPATCH_METHOD) &&
((pEntry->pfn == NULL && pEntry->pfnSet == NULL) ||
(pEntry->pfn == NULL && pEntry->pfnSet != NULL) ||
(pEntry->pfn != NULL && pEntry->pfnSet != NULL)))
{
// the entry describes a property but a method call is being
// attempted -- change it to a property get/set based on the
// number of parameters being passed.
wFlags &= ~DISPATCH_METHOD;
UINT nExpectedArgs = pEntry->lpszParams != NULL ?
(UINT)lstrlenA(pEntry->lpszParams) : 0;
if (pDispParams->cArgs <= nExpectedArgs)
{
// no extra param -- so treat as property get
wFlags |= DISPATCH_PROPERTYGET;
}
else
{
// extra params -- treat as property set
wFlags |= DISPATCH_PROPERTYPUTREF;
pDispParams->cNamedArgs = 1;
}
}
When the same method is called from Python, the COleDispatchImpl::Invoke is
initially called with the flag DISPATCH_PROPERTYGET.
This is of cause wrong, since the call must be interpret as a
DISPATCH_PROPERTYPUTREF, then the method call fails with wrong number of
arguments.
Why are Python Script misinterpreting this method call?
Is Python Script not able to handle propget and propput methods as defined
in the OLD file?
Can I in the call to the method in Python Script somehow tell that it is the
propput version of the method I want to call?
Update 1
The above code calls the following macro:
DISP_PROPERTY_PARAM_ID(CMyScriptingObject,"Property",100,GetProperty,SetProp
erty,VT_VARIANT,VTS_BSTR)
Here a Set and a Get (in this case SetProperty and GetProperty) methods are
created. I now found out, that if I implicitly calls the SetProperty method,
it works:
Session.SetProperty("Test",2)
Intuitively I would then expect that GetProperty would work like this:
myProp = Session.GetProperty("Test")
However this calls fails with the following error:
[13:32:49] Python Test
[13:32:52] Scripting
Python ActiveX Scripting Engine
Error: Traceback (most recent call last):
File "<Script Block >", line 20, in <module>
myProp = Session.GetProperty("Test")
File "C:\Python27\lib\site-
packages\win32comext\axscript\client\pyscript.py", line 105, in __getattr__
return getattr(self._scriptItem_.dispatchContainer,attr)
File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line
522, in __getattr__
raise AttributeError("%s.%s" % (self._username_, attr))
AttributeError: Session.GetProperty
In line 20 At column -1 Error Code: 0
Source line: myProp = Session.GetProperty("Test")
It must be related to multiple arguments. However it could also be that I
don't understand the syntax of Python compared to the simpler VBScript.
Update 2
Ok, now I used the PythonWin program to load the tool COM Makepy Utility on
the registered tlb of my COM object. Here I can see:
# The method Property is actually a property, but must be used as a method
to correctly pass the arguments
def Property(self, name=defaultNamedNotOptArg, val=pythoncom.Missing):
return self._ApplyTypes_(100, 2, (3, 0), ((8, 1), (16396, 10)),
u'Property', None,name
, val)
# The method SetProperty is actually a property, but must be used as a
method to correctly pass the arguments
def SetProperty(self, name=defaultNamedNotOptArg,
val=defaultNamedNotOptArg):
return self._oleobj_.InvokeTypes(100, LCID, 4, (3, 0), ((8, 1), (12,
1)),name
, val)
So, I guess that this is why I need to call SetProperty and why GetProperty
does not exist. But the Property exist, but how do I call it?
-cpede