Python - 获取win32com类的所有属性/属性列表

9

我是Python的新手。我需要从Outlook中提取电子邮件并获取所有属性/属性。

一个一个地检索属性,对于那些我知道它们存在的属性/属性来说,这样做很好(.Subject,.Body等)。

但是,我需要获得所有可能的属性。这就是我的问题所在。 我已经寻找了几个小时,唯一找到的答案都是使用:

  • vars()
  • dir()
  • inspect.getmembers(obj)
  • __dict__
  • 等等。
这些方法无法给我像以下这些属性列表:

  • .Subject
  • .Body
  • .SentOn
  • 等等。
有人能帮忙吗?

这是我测试笔记本的摘录:

####### Retrieve email from Outlook #######
import win32com.client
objOutlookMAPI=win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
​    
​### Define folder
objOlFolder = objOutlookMAPI.GetDefaultFolder(6)

​### Retrieve ant print email
objOlMessages = objOlFolder.Items
​
# objMessage : class 'win32com.client.CDispatch'
objMessage = objOlMessages.GetLast()
print(objMessage.Subject)    

> Are you going to Las Vegas for Black Hat, DefCon, Bsides, or Hacking Diversity? Either or join us on our adventures!

vars(objMessage)

> {'_builtMethods_': {},
 '_enum_': None,
 '_lazydata_': (<PyITypeInfo at 0x0000021EC7B7D170 with obj at 0x0000021EC7B4B2F8>,
  <PyITypeComp at 0x0000021EC7B7D620 with obj at 0x0000021EC7B4B058>),
 '_mapCachedItems_': {},
 '_oleobj_': <PyIDispatch at 0x0000021EC7B7D290 with obj at 0x0000021EC7B4AAA8>,
 '_olerepr_': <win32com.client.build.LazyDispatchItem at 0x21ec8a7ba90>,
 '_unicode_to_string_': None,
 '_username_': 'GetLast'}


    dir(objMessage)
    #import inspect
    #inspect.getmembers(objMessage)

> [`'_ApplyTypes_'`,
 `'_FlagAsMethod'`,
 `'_LazyAddAttr_'`,
 `'_NewEnum'`,
 `'_Release_'`,
 `'__AttrToID__'`,
 `'__LazyMap__'`,
 `'__bool__'`,
 `'__call__'`,
 `'__class__'`,
 `'__delattr__'`,
 `'__dict__'`,
 `'__dir__'`,
 `'__doc__'`,
 `'__eq__'`,
 `'__format__'`,
 `'__ge__'`,
 `'__getattr__'`,
 `'__getattribute__'`,
 `'__getitem__'`,
 `'__gt__'`,
 `'__hash__'`,
 `'__init__'`,
 `'__init_subclass__'`,
 `'__int__'`,
 `'__le__'`,
 `'__len__'`,
 `'__lt__'`,
 `'__module__'`,
 `'__ne__'`,
 `'__new__'`,
 `'__reduce__'`,
 `'__reduce_ex__'`,
 `'__repr__'`,
 `'__setattr__'`,
 `'__setitem__'`,
 `'__sizeof__'`,
 `'__str__'`,
 `'__subclasshook__'`,
 `'__weakref__'`,
 `'_builtMethods_'`,
 `'_enum_'`,
 `'_find_dispatch_type_'`,
 `'_get_good_object_'`,
 `'_get_good_single_object_'`,
 `'_lazydata_'`,
 `'_make_method_'`,
 `'_mapCachedItems_'`,
 `'_oleobj_'`,
 `'_olerepr_'`,
 `'_print_details_'`,
 `'_proc_'`,
 `'_unicode_to_string_'`,
 `'_username_'`,
 `'_wrap_dispatch_'`]

__getattr____getattribute__中可能有一些魔法。 - Stephen Rauch
1
因此,在进一步研究后,似乎没有简单的方法来内省COM对象。您可能需要使用MSDN文档或VBA调试器。 - Stephen Rauch
一般来说,COM对象无法枚举它们的方法,因此win32com无法解决这个问题。但是:(1)如果它是支持IDispatchExIDispatch接口,您可以直接QueryInterface到该接口并调用GetIDsOfNames方法。(2)如果它是不支持IDispatchExIDispatch接口,则可以在其上调用GetTypeInfo。(2a)如果生成的ITypeInfo支持ITypeInfo2,则可以QI该接口并对其进行枚举。(2b)如果不支持,但它确实支持GetTypeAttrGetFuncDesc,则可以使用这些方法。(3)如果都不是,则没有办法。 - abarnert
尝试使用win32com搜索这些方法名称,看看是否有任何示例。我在快速搜索中没有找到任何内容,但我找到了这个问题,针对ATL,它涵盖了如何使用所有这些方法,如果您知道如何从C++进行翻译。 - abarnert
非常感谢你们的回答。 我还发现了这个网站http://timgolden.me.uk/pywin32-docs/html/com/win32com/HTML/PythonCOM.html和这个https://www.productiverage.com/idispatch-iwastedtimeonthis-but-ilearntlots。从我的理解来看,这里可能有我正在寻找的答案。但是这超出了我的能力范围(比如将C++移植到Python)。 如果没有人有准备好的Python代码,我想我将不得不通过VB并使用VBA变量资源管理器或对象资源管理器来探索属性/属性... 再次感谢。 - NewbieOneCannotBe
2个回答

2
为了后人参考,我在这里找到了我需要的内容,它在这个页面的AppointmentItem对象中: Outlook Visual Basic for Applications (VBA) reference 只需在页面左侧展开该对象,然后展开属性。 我在那里找到了我需要的一切。 还有一个MeetingItem对象,我还在努力弄清楚它们之间的区别(听起来很明显,但我得到的许多约会实际上都是会议(即有与会者)。

0

我找到了一种方法:

计划是在第二个演示文稿中创建一个宏,你可以从Python中调用它,并且借助tlbinf32.dll的帮助,能够获取对象的所有成员。

第二个演示文稿

  1. 首先,您需要下载 tlbinf32.dll
    对于64位系统:请按照此指南正确设置32位DLL!我还遇到了HP Print Scan Doctor Service的问题:我需要禁用该服务并卸载HP Smart。(然后重新启动)
  2. 创建一个新的.pptm文件(带有宏的pptx),并打开它(我将其命名为GetMembersUtil.pptm
  3. 在该演示文稿中,创建一个新的宏(名称不重要)并编辑它(查看->宏)
  4. 在宏之后添加对刚刚下载的tlbinf32.dll的引用(工具->引用)
  5. 在宏之后粘贴以下函数
Function GetMembers(obj)
    ' Declare vars
    Dim TLI
    Dim TypeInfo
    Dim Members
    
    ' Create new ArrayList since we don't know how many Members obj has
    Set Members = CreateObject("System.Collections.ArrayList")
    
    ' Initialize tlbinf
    Set TLI = CreateObject("TLI.TLIApplication")
    Set TypeInfo = TLI.InterfaceInfoFromObject(obj)
    
    ' iterate over each Member
    For Each MemberInfo In TypeInfo.Members
        Members.Add MemberInfo.Name
    Next
    
    ' Convert ArrayList back to native vba Array because you can't return an ArrayList
    GetMembers = Members.ToArray()
    
End Function

这个函数接受一个对象作为输入,并返回该对象的所有成员

  1. 将您的演示文稿保存在Python文件的本地目录中

Python端

为了能够使用宏,我们需要确保刚刚创建的演示文稿已经打开

def vba_get_members(app: win32com.client.CDispatch, obj: win32com.client.CDispatch) -> tuple[str, ...]:
    # os.path.abspath is very important
    ensure_opened(app, os.path.abspath("GetMembersUtil.pptm"))
    return app.Run("GetMembersUtil.pptm!GetMembers", obj)

def ensure_opened(app: win32com.client.CDispatch, file_path):
    # check if presentation is already opened
    for presentation in app.Presentations:
        pp_filepath = os.path.join(presentation.Path, presentation.Name)

        if pp_filepath == file_path:
            # presentation already opened
            break
    else:
        # presentation wasn't already opened
        app.Presentations.Open(file_path)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接