Jump to content

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

AutoHotkey_L - IsMemberOf()


  • Please log in to reply
5 replies to this topic
jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
First off, this is more of a possible suggestion than an actual wish. Also, this idea is directly from Ruby (WIN32OLE module -> ole_respond_to? method)

Currently there is no mechanism available for scripts to detect or handle specific COM errors.

One option might be to eliminate COM errors before they happen. Not unlike the HasKey() method for AHK objects, it would be nice to know if a Com Object will respond to a property/method call. For instance, you could test for the existence of a webpage element before invoking it, rather than trying and seeing if there's a COM Error:
all := pwb.document.all
if all.respond_to("q")
	all.q.value := "Search Value"

On a side note, I'm trying to keep away from the thought process of "Make AHK more like Ruby or Javascript" - I just thought this feature would be nice.

EDIT - Solution discussed below:
IsMemberOf(obj, name) {
	return, DllCall(NumGet(NumGet(1*p:=ComObjValue(obj))+A_PtrSize*5), "Ptr",p, "Ptr",VarSetCapacity(iid,16,0)*0+&iid, "Ptr*",&name, "UInt",1, "UInt",1024, "Int*",dispID)=0 && dispID+1
}
Example usage:
all := pwb.document.all
if IsMemeberOf(all, "q")
	all.q.value := "Search Value"


Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007
You can do that yourself readily.
IsMemberOf(obj, name)
{
    Return DllCall(NumGet(NumGet(1*p:=ComObjUnwrap(obj))+A_PtrSize*5), "Ptr", p, "Ptr", VarSetCapacity(iid,16,0)*0+&iid, "Ptr*", &name, "UInt", 1, "UInt", 1024, "Int*", dispID:=-1)=0 && dispID+1 ; for UNICODE builds
}
BTW, you have to (COM_)Release the unwrapped pointer p with the official AHK_L.

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009

You can do that yourself readily.

Well, I'm glad you have confidence in me :) .

BTW, you have to (COM_)Release the unwrapped pointer p with the official AHK_L.

So, something like this?
IsMemberOf(obj, name)
{
	out := DllCall(NumGet(NumGet(1*p:=ComObjUnwrap(obj))+A_PtrSize*5), "Ptr", p, "Ptr", VarSetCapacity(iid,16,0)*0+&iid, "Ptr*", &name, "UInt", 1, "UInt", 1024, "Int*", dispID)=0 && dispID+1
	DllCall(NumGet(NumGet(1*p)+8), "Uint", p) ; COM_Release
	return, out
}
Also, I'm not sure if you have any plans of ever modifying the COM Library to use Native COM, but if you do (& if a function like this isn't worth adding to AHK natively), this would be a good addition to the COM Library, IMO.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
Off-topic: I suggest you use ObjRelease(p) in place of COM_Release (which isn't x64-compatible).

Sean
  • Members
  • 2462 posts
  • Last active: Feb 07 2012 04:00 AM
  • Joined: 12 Feb 2007

So, something like this?

Actually I was against this idea of AddRef as it could be cumbersome as in this case, but as it happened, the best practice IMO is to make a rule to never leave a COM object pointer floating in raw, i.e., enwrap it again. This can be used with non-dispatchable objects too. Of course you can call ObjRelease(p) instead as Lexikos suggested.
IsMemberOf(obj, name)
{
   out := DllCall(NumGet(NumGet(1*p:=ComObjUnwrap(obj))+A_PtrSize*5), "Ptr", p, "Ptr", VarSetCapacity(iid,16,0)*0+&iid, "Ptr*", &name, "UInt", 1, "UInt", 1024, "Int*", dispID)=0 && dispID+1
   ComObjEnwrap(p) ; no, it'll have no effect. See PS at the end.
   return, out
}
And, I forgot to mention. Don't ever use like this, it'll leave the object unreleased.
DllCall(NumGet(NumGet(ComObjUnwrap(obj))+A_PtrSize*5), "Ptr", ComObjUnwrap(obj), ...)

(& if a function like this isn't worth adding to AHK natively)

I didn't like the idea of supporting respond_to (or whatever name it is) natively, since there exists a chance that some objects can have a member of the specific name even though using underscore in the middle of name is discouraged. If it ever needed, the best would be the following (which I reserved for Default member), or as a separate function.
obj.(name)

Also, I'm not sure if you have any plans of ever modifying the COM Library to use Native COM

No I don't have a plan to do it as I don't see the need of it.

PS. Well, I now see ComObjEnwrap was also changed to do AddRef.

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
If it's possible to see if a com object will respond to a property/method call, would it be possible to list/enumerate all the members?

EDIT: see iTypeInfo - Get info from TypeAttr Struct - Enum Com Members