[pywin32-bugs] [ pywin32-Bugs-3525912 ] InvokeTypes error using win32com v2.17
OLD project page for the Python extensions for Windows
Brought to you by:
mhammond
From: SourceForge.net <no...@so...> - 2012-06-01 23:30:50
|
Bugs item #3525912, was opened at 2012-05-11 10:37 Message generated for change (Comment added) made by mike_fox You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=551954&aid=3525912&group_id=78018 Please note that this message will contain a full copy of the comment thread, including the initial issue submission, for this request, not just the latest update. Category: win32 Group: None Status: Open Resolution: None Priority: 5 Private: No Submitted By: Mike Fox (mike_fox) Assigned to: Nobody/Anonymous (nobody) Summary: InvokeTypes error using win32com v2.17 Initial Comment: I think we have found a bug in win32com 2.17. We are using it with Python 2.7.2. We are calling a proprietary DLL named PATE, which provides APIs to a database named Enovia from the Dassault corporation. The Enovia client is linked to a CAD program named CATIA so we must conjure objects of both CATIA and Enovia as shown in the code snippet below. The strApplicationID is a password administered by my company and has nothing to do with the PATE DLL itself. Rather, PATE should pass the strApplicationID to the Enovia server, which should authenticate the session. ==================================================================== import win32com.client, win32com.client.gencache, win32com.client.selecttlb strPATECLSID = '{9BB3CB79-7098-47D0-83A2-F8F56D236DC8}' strPATEclassCLSID = '{9A1F3C8E-46B7-4CFA-A820-E4256ECD53B5}' self.objCATIA = win32com.client.GetActiveObject('CATIA.Application') win32com.client.gencache.EnsureModule(strPATECLSID, 0, 0, 0) self.objBase= win32com.client.gencache.GetClassForCLSID(strPATEclassCLSID) self.__objPATECOM = self.objBase(self.objCATIA) strApplicationID = <secret> try: self.__objPATECOM.SetApplicationID(strApplicationID) except (pywintypes.com_error), _e: print "Connection error: %s" %(_e) return False ==================================================================== When we use win32com 2.16 the code above works fine but when we use win32com 2.17 it throws the error message shown below. File testKBE_PATECAKE.py, line 367 in ConnectToENOVIA self.__objPATECOM.SetApplicationID(strApplicationID) File "C:\Python27\lib\site-packages\win32com\gen_py\9BB3CB79 -7098-47D0-83A2-F8 F56D236DC8x0x0x0.py", line 457 in SetApplicationID return self._oleobj_.InvokeTypes(1610940417, LCID, 1, (24, 0), ((16396, 1),) , iAID File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line 516 in __getattr__ raise AttributeError("%s.%s" % (self._username_, attr)) AttributeEror: CATIA.Application.InvokeTypes ---------------------------------------------------------------------- >Comment By: Mike Fox (mike_fox) Date: 2012-06-01 16:30 Message: I put some print statements into the DispatchBaseClass.__init__ method as you suggested. That method checks whether the oobj == None, then checks whether oobj is an instance of DispatchBaseClass. Both tests fail so the QueryInterface method is never called and the raw oobj is put into the DispatchBaseClass.__dict__ When I printed the raw oobj (that was input to the __init__ method) it printed <PyIDispatch at 0x000000002371440 with obj at 0x000000000048E258> If I change the 6th line of the __init__ method from elif isinstance(oobj, DispatchBaseClass): to else: the code runs without throwing any errors. What does that mean? ---------------------------------------------------------------------- Comment By: Mark Hammond (mhammond) Date: 2012-05-30 16:42 Message: It looks like the genpy idea I had was wrong - the objects are the same in both examples. What should happen is that the line: self.__objPATECOM = self.objBase(self.objCATIA) end up calling DispatchBaseClass.__init__ which is in win32com\client\__init__.py. What *should* happen, and appears to be happening in 216 is it should enter the branch: elif isinstance(oobj, DispatchBaseClass): try: oobj = oobj._oleobj_.QueryInterface(self.CLSID, pythoncom.IID_IDispatch) # Must be a valid COM instance except pythoncom.com_error, details: import winerror # Some stupid objects fail here, even tho it is _already_ IDispatch!!?? # Eg, Lotus notes. # So just let it use the existing object if E_NOINTERFACE if details.hresult != winerror.E_NOINTERFACE: raise oobj = oobj._oleobj_ In the working case it just does the QI so oobj ends up as a "raw" IDispatch. In your failing 217 scenario, it seems to be either not hitting that first condition at all, or enters that block but hits the "except pythoncom.com_error" block. You might want to instrument that code with prints to try and (a) confirm I'm correct in the working case and (b) work out how it fails in the failing case (ie, whether the 'if' statement simply isn't entered at all or it hits the exception). ---------------------------------------------------------------------- Comment By: Mike Fox (mike_fox) Date: 2012-05-30 11:11 Message: Sorry for the delay. I added print statements after lines 4, 6, and 7 (in the code shown in my original post). With version 2.16 (pywin32-216.win-amd64-py2.7) I get the following correct output: self.objCATIA= <COMObject CATIA.Application> self.objBase= win32com.gen_py.9BB3CB79-7098-47D0-83A2-F8F56D236DC8x0x0x0.PATECOM self.__objPATECOM= <win32com.gen_py.CATIA V5 BOEPATEAutomationInterfaces Object Library.PATECOM instance at 0x44540104> Then I ran the same sript with version 2.17 (pywin32-217.win-amd64-py2.7) and got the following: self.objCATIA= <COMObject CATIA.Application> self.objBase= win32com.gen_py.9BB3CB79-7098-47D0-83A2-F8F56D236DC8x0x0x0.PATECOM self.__objPATECOM= <win32com.gen_py.CATIA V5 BOEPATEAutomationInterfaces Object Library.PATECOM instance at 0x44540104> Traceback (moste recent call last): File testKBE_PATECAKE.py, line 370 in ConnectToENOVIA self.__objPATECOM.SetApplicationID(strApplicationID) File "C:\Python27\lib\site-packages\win32com\gen_py\9BB3CB79 -7098-47D0-83A2-F8 F56D236DC8x0x0x0.py", line 457 in SetApplicationID return self._oleobj_.InvokeTypes(1610940417, LCID, 1, (24, 0), ((16396, 1),), iAID File "C:\Python27\lib\site-packages\win32com\client\dynamic.py", line 516 in __getattr__ raise AttributeError("%s.%s" % (self._username_, attr)) AttributeEror: CATIA.Application.InvokeTypes ---------------------------------------------------------------------- Comment By: Mark Hammond (mhammond) Date: 2012-05-15 17:34 Message: Can you please modify your test code to add: print self.objCATIA After creating it, and tell me what it prints in both the failing and working cases? ---------------------------------------------------------------------- Comment By: Mike Fox (mike_fox) Date: 2012-05-15 17:32 Message: To Mark Hammond: I don't think the problem is caused by a pre-existing wrapper in the gen_py folder as you suggested in your comment. When I uninstalled version 2.17 of pywin32 and installed version 2.16 on the same PC (with the contents of the gen_py folder unchanged) I was able to call the SetApplicationID method without it throwing an error. ---------------------------------------------------------------------- Comment By: Mark Hammond (mhammond) Date: 2012-05-11 19:51 Message: I suspect the problem is that previously you have makepy support generated for the 'CATIA.Application' object which should make things work. The problem is that when you do: self.__objPATECOM = self.objBase(self.objCATIA) The DispatchBaseClass.__init__ function in win32com\client\__init__.py checks to see if the object is itself a makepy generated object and will work correctly if it is. Even though, this really is a bug as we should handle that situation. A fix would probably be to change the line in DispatchBaseClass.__init__ from: elif isinstance(oobj, DispatchBaseClass): to elif hasattr(oobj, "_oleobj_"): ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=551954&aid=3525912&group_id=78018 |