简体   繁体   中英

Python - Get list of all attributes/properties of a win32com class

I am a newbie in Python. I have to extract emails from Outlook and get all attributes/properties of the emails.

Retrieving properties one by one, for the attributes/properties that I know they exist works fine (.Subject, .Body, etc.).

But, I need to get all possible attributes. That's where my problem is. I have been looking for hours, the only answers I found were using:

  • vars()
  • dir()
  • inspect.getmembers(obj)
  • __dict__
  • etc.
Which does not give me the list of properties like:

  • .Subject
  • .Body
  • .SentOn
  • etc.
Could someone help ?

Here is the extract of my test Notebook :

 ####### 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_'`] ####### 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_'`] ####### 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_'`]

For posterity here, I found what I needed in the AppointmentItem object on this page:

Outlook Visual Basic for Applications (VBA) reference

Just expand that object on the left side of the page, and then expand properties. Found everything I needed there. Also a MeetingItem object, still in the process of figuring out the difference (which sounds like it's obvious, but a lot of the appointments I'm getting back are actually meetings (ie have attendees).

I found a way to do it, actually:

The plan is to create a macro in a second presentation that you call from within python and that is, with the help of tlbinf32.dll, able to get all members of an object.

The Second Presentation

  1. To start, you want to download the tlbinf32.dll .
    FOR 64-bit SYSTEMS: Follow this guide to properly set up the 32-bit-DLL! I also had problems with the HP Print Scan Doctor Service : I needed to disable that service and uninstall HP Smart . (and reboot)
  2. Create a new .pptm file (pptx with macros) and open it (I named it GetMembersUtil.pptm )
  3. In that presentation, create a new macro (the name is irrelevant) and edit it (View->Macros)
  4. Add a reference to your tlbinf32.dll that you just downloaded (Tools->References)
  5. Paste the following function after the macro
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

this function takes an object as input and returns all the members of that object

  1. Save your presentation in the local directory of your python file

The Python Side

To be able to use the macro we need to make sure that the presentation we just created is openend

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM