Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Enumerate Com Object Members - iTypeInfo


  • Please log in to reply
3 replies to this topic
jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
See here for more info.

sd := ComObjCreate("Scripting.Dictionary")
Members := EnumComMembers(sd)

Gui, Add, ListView, x12 y5 w200 h420, ID|Name|Kind
Loop Parse, Members, `n
{
   StringSplit, item, A_LoopField, `t
   LV_Add("", item1, item2, item3)
}
LV_ModifyCol()
Gui, Show, , Excel Members
return

GuiClose:
   ExitApp

EnumComMembers(pti) {
   static InvKind := {1:"method", 2:"get", 4:"put", 8:"putref"}
   if ComObjType(pti)=9 { ; if Com Object, get iTypeInfo Interface
      ptr := ComObjValue(pti)
      { ; Check if *ptr* has ITypeInfo Interface
         GetTypeInfoCount := vtable(ptr, 3)
         DllCall(GetTypeInfoCount, "ptr",ptr, "ptr*",HasITypeInfo)
         if Not HasITypeInfo {
            MsgBox ITypeInfo Interface not supported
            return
         }
      }
      GetTypeInfo := vTable(ptr, 4)
      if DllCall(GetTypeInfo, "ptr",ptr, "uint",0, "uint",0, "ptr*",pti)!=0
         return
   }
   { ; Com Methods
      GetTypeAttr := vTable(pti, 3)
      ReleaseTypeAttr := vTable(pti, 19)
      GetRefTypeOfImplType := vTable(pti, 8)
      GetRefTypeInfo := vTable(pti, 14)
      GetFuncDesc := vTable(pti, 5)
      ReleaseFuncDesc := vTable(pti, 20)
      GetDocumentation := vTable(pti, 12)
   }
   { ; get cFuncs (number of functions)
      DllCall(GetTypeAttr, "ptr",pti, "ptr*",typeAttr)
      cFuncs := NumGet(typeAttr+0, 40+A_PtrSize, "short")
      cImplTypes := NumGet(typeAttr+0, 44+A_PtrSize, "short")
      DllCall(ReleaseTypeAttr, "ptr",pti, "ptr",typeAttr)
   }
   if cImplTypes { ; Get Inherited Class (cImplTypes should be true)
      DllCall(GetRefTypeOfImplType, "ptr",pti, "int",0, "int*",pRefType)
      DllCall(GetRefTypeInfo, "ptr",pti, "ptr",pRefType, "ptr*", pti2)
      DllCall(GetDocumentation, "ptr",pti2, "int",-1, "ptr*",Name, "ptr",0, "ptr",0, "ptr",0) ; get Interface Name
      if StrGet(Name) != "IDispatch"
         t .= EnumComMembers(pti2) "`n"
      else
         ObjRelease(pti2)
   }
   Loop, %cFuncs% { ; get Member IDs
      DllCall(GetFuncDesc, "ptr",pti, "int",A_Index-1, "ptr*",FuncDesc)
      ID := NumGet(FuncDesc+0, "short") ; get Member ID
      n := NumGet(FuncDesc+0, 4+3*A_PtrSize, "int") ; get InvKind
      ; Args := NumGet(FuncDesc+0, 12+3*A_PtrSize, "short") ; get Num of Args
      ; Opt := NumGet(FuncDesc+0, 14+3*A_PtrSize, "short") ; get Num of Opt Args
      DllCall(ReleaseFuncDesc, "ptr",pti, "ptr",FuncDesc)
      DllCall(GetDocumentation, "ptr",pti, "int",ID, "ptr*",Name, "ptr",0, "ptr",0, "ptr",0)
      if StrGet(Name, "UTF-16") ; Exclude Members that didn't return a Name
         t .= ID "`t" StrGet(Name, "UTF-16") "`t" InvKind[n] "`n"
   }
   { ; formatting & cleanup
      t := SubStr(t,1,-1)
      Sort, t, ND`n
      ObjRelease(pti)
   }
   return t
}
vTable(ptr, n) { ; see ComObjQuery documentation
    return NumGet(NumGet(ptr+0), n*A_PtrSize)
}


fragman
  • Members
  • 1591 posts
  • Last active: Nov 12 2012 08:51 PM
  • Joined: 13 Oct 2009
Very nice. Small suggestion: Make it return an object so for-loop iteration is possible.

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
I originally did that, but it's not as simple to sort the members by ID. I suppose the function could just parse the list & assign it to an object, but then several AHK commands return lists ...

chaidy
  • Members
  • 57 posts
  • Last active: Oct 21 2015 05:53 PM
  • Joined: 20 Apr 2010
shell := ComObjCreate("Shell.Application")
Members := EnumComMembers(shell)
MsgBox % Members ; result = ""