l...@sina.com schrieb:
>  Hi, 
> 
> there is a bug in comtypes.client.GetBestInterface, as this:
> 
> ----
> ## the following code works fine
> from comtypes.client import CreateObject
> wscriptObj = CreateObject("Wscript.Shell",dynamic=True)
> print(wscriptObj.CurrentDirectory)
> wscriptObj.run("cmd.exe /c notepad.exe",0)
> 
> # But, when drop the "dynamic=True", it will fail
> from comtypes.client import CreateObject
> wscriptObj = CreateObject("Wscript.Shell")
> print(wscriptObj.CurrentDirectory)   # Failed, AttributeError: 
> CurrentDirectory
> wscriptObj.run("cmd.exe /c notepad.exe",0)
> ----
> 
> Turns out that when progid="Wscript.Shell", in
> comtypes.client.GetBestInterface, the pci.GetClassInfo() returned
> TypeInfo of the default interface IWshShell3, not of the supposed
> CoClass WshShell. GetBestInterface searched IWshShell3, find what it
> implemented - IWshShell2, which has no property CurrentDirectory.

Yes, I see the problem.

> 
> So I think here need an if stmt, such as "if (str(ta.guid) == punk.clsid): go 
> best interface",
> or, try IDispatch.GetTypeInfo first.

I do not really understand what you mean.

But I have attached a patch for comtypes\client\__init__.py which should fix 
the problem.

Index: __init__.py
===================================================================
--- __init__.py (revision 564)
+++ __init__.py (working copy)
@@ -70,18 +70,28 @@
         tinfo = pci.GetClassInfo() # TypeInfo for the CoClass
         # find the interface marked as default
         ta = tinfo.GetTypeAttr()
-        for index in range(ta.cImplTypes):
-            if tinfo.GetImplTypeFlags(index) == 1:
-                break
-        else:
-            if ta.cImplTypes != 1:
-                # Hm, should we use dynamic now?
-                raise TypeError("No default interface found")
-            # Only one interface implemented, use that (even if
-            # not marked as default).
-            index = 0
-        href = tinfo.GetRefTypeOfImplType(index)
-        tinfo = tinfo.GetRefTypeInfo(href)
+        if ta.typekind in (3, 4): # TKIND_INTERFACE, TKIND_DISPATCH
+            # The tinfo that we got is an interface, we use this as
+            # the 'best interface'
+            pass
+        elif ta.typekind == 5: # TKIND_COCLASS
+            # The tinfo describes the coclass. We have to find out
+            # which interfaces this coclass implements and use the
+            # 'best' one.
+            for index in range(ta.cImplTypes):
+                if tinfo.GetImplTypeFlags(index) == 1: # IMPLTYPEFLAG_FDEFAULT
+                    # This is the default interface
+                    href = tinfo.GetRefTypeOfImplType(index)
+                    tinfo = tinfo.GetRefTypeInfo(href)
+                    break
+            else:
+                if ta.cImplTypes != 1:
+                    # Hm, should we use dynamic now?
+                    raise TypeError("No default interface found")
+                # Only one interface implemented, use that (even if
+                # not marked as default).
+                href = tinfo.GetRefTypeOfImplType(0)
+                tinfo = tinfo.GetRefTypeInfo(href)
     except comtypes.COMError:
         logger.debug("Does NOT implement IProvideClassInfo/IProvideClassInfo2")
         try:


------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev
_______________________________________________
comtypes-users mailing list
comtypes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/comtypes-users

Reply via email to