从 Word.Application 对象获取 Document 对象时,其成员未从 gencache 缓存中填充,而 VBSEdit 能够获取它们

When getting Document object from Word.Application object, its members are not filled from gencache cache while VBSEdit is able to get them

https://mail.python.org/pipermail/python-win32/2004-October/002582.html 完美地总结了我的问题(针对我的情况进行了轻微的编辑更新):

I would like to have a Word Document instance with all methods and properties visible during interactive session. This is my currnet apporach:

>>> from win32com.client import gencache, Dispatch
>>> gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 1, bForDemand=True) 
<module 'win32com.gen_py.00020905-0000-0000-C000-000000000046x0x8x1' from
'C:\DOCUME~1\osuchw\LOCALS~1\Temp\gen_py.3[=11=]020905-0000-0000-C000-000000000046x0x8x1\__init__.py'>
>>> word = Dispatch('Word.Application')
>>> word 
<win32com.gen_py.Microsoft Word 12.0 Object Library._Application instance at 0x18074720>
>>> doc = word.Documents.Add()
>>> doc 
<win32com.gen_py.None.Document>

As you can see I am getting a dynamic object not knowing its methods/properties. What I would like to get is something like:

>>> doc = Dispatch('Word.Document')
>>> doc 
<win32com.gen_py.Microsoft Word 12.0 Object Library._Document instance at 0x37038040>

我想我还需要从另一个类型库(例如 "Office 12.0 Object Library")生成一个包装器,但没有提示它是哪个。同样,HKEY_CLASSES_ROOT\CLSID\{00020906-0000-0000-C000-000000000046} 处没有 TypeLib 子项,而 doc.CLSID 会生成该子项。

该线程中的唯一答案指向 RTFM 一本关于 Word 编程的一般书籍 w/o 任何提示(我严重怀疑它甚至提到类型库)。

我最终使用以下代码为机器上的所有类型库生成了包装器:

import win32com.client.selecttlb    
ii=win32com.client.selecttlb.EnumTlbs()
ii=[i.desc for i in ii]
# one typelib - "Visual Basic runtime objects and procedures [6.0]" - produced an error
for i in ii: subprocess.call(['python','-m','win32com.client.makepy',i])

但即使在这种情况下,它仍然是 win32com.gen_py.None.Document


最奇怪的是对象的class识别并存在于缓存中:

>>> ad=win32com.client.gencache.EnsureDispatch("Word.Document")
>>> d = w.ActiveDocument
>>> d.__class__
<class win32com.gen_py.00020905-0000-0000-C000-000000000046x0x8x4.Document at 0x02A101B8>
>>> ad.__class__
<class win32com.gen_py.00020905-0000-0000-C000-000000000046x0x8x4._Document at 0x02A07B20>
>>> len(dir(ad.__class__))
141
>>> len(dir(d.__class__))
11

同时,VBA编辑器和VBSEdit列出w.ActiveDocument的成员就好了。他们是怎么做到的,为什么 pythoncom 不能这样做?

d._dispobj_ 包含所有成员,因此可以用来代替 d

眼前的问题解决了

但我仍然不知道发生了什么。