GetActiveObjects Topic is solved

Get help for the alpha version of AutoHotkey v2 here. Please state the v2 version you are working with in the title when making a new topic.
RNDLDVL
Posts: 15
Joined: 04 Oct 2015, 10:48

GetActiveObjects

19 Aug 2020, 03:28

Not sure if this is the right section. Anyone happen to have the v2 version of this function? I've tried porting it basing on the v2 documentation but I'm not sure how the DllCalls work themselves so I'm not sure what I am doing wrong or perhaps an alternative to fetching all active specific COM objects of a certain type in v2.

v1 Original:

Code: Select all

GetActiveObjects(Prefix:="",CaseSensitive:=false) {
	objects := {}
	DllCall("ole32\CoGetMalloc", "uint", 1, "ptr*", malloc) ; malloc: IMalloc
	DllCall("ole32\CreateBindCtx", "uint", 0, "ptr*", bindCtx) ; bindCtx: IBindCtx
	DllCall(NumGet(NumGet(bindCtx+0)+8*A_PtrSize), "ptr", bindCtx, "ptr*", rot) ; rot: IRunningObjectTable
	DllCall(NumGet(NumGet(rot+0)+9*A_PtrSize), "ptr", rot, "ptr*", enum) ; enum: IEnumMoniker
	while DllCall(NumGet(NumGet(enum+0)+3*A_PtrSize), "ptr", enum, "uint", 1, "ptr*", mon, "ptr", 0) = 0 ; mon: IMoniker
	{
		DllCall(NumGet(NumGet(mon+0)+20*A_PtrSize), "ptr", mon, "ptr", bindCtx, "ptr", 0, "ptr*", pname) ; GetDisplayName
		name := StrGet(pname, "UTF-16")
		DllCall(NumGet(NumGet(malloc+0)+5*A_PtrSize), "ptr", malloc, "ptr", pname) ; Free
		if InStr(name, Prefix, CaseSensitive) = 1 {
			DllCall(NumGet(NumGet(rot+0)+6*A_PtrSize), "ptr", rot, "ptr", mon, "ptr*", punk) ; GetObject
	; Wrap the pointer as IDispatch if available, otherwise as IUnknown.
			if (pdsp := ComObjQuery(punk, "{00020400-0000-0000-C000-000000000046}"))
				obj := ComObject(9, pdsp, 1), ObjRelease(punk)
			else
				obj := ComObject(13, punk, 1)
	; Store it in the return array by suffix.
			objects[SubStr(name, StrLen(Prefix) + 1)] := obj
		}
		ObjRelease(mon)
	}
	ObjRelease(enum)
	ObjRelease(rot)
	ObjRelease(bindCtx)
	ObjRelease(malloc)
	return objects
}
v2 Attempt:

Code: Select all

GetActiveObjects(Prefix:="",CaseSensitive:=false) {
        objects := {}
        malloc := DllCall("ole32\CoGetMalloc", "uint", 1, "Cdecl ptr*") ; malloc: IMalloc
        bindCtx := DllCall("ole32\CreateBindCtx", "uint", 0, "Cdecl ptr*", ) ; bindCtx: IBindCtx
        rot := DllCall(NumGet(NumGet(bindCtx+0, "UPtr")+8*A_PtrSize, "UPtr"), "ptr", bindCtx, "Cdecl ptr*") ; rot: IRunningObjectTable
        enum := DllCall(NumGet(NumGet(rot+0, "UPtr")+9*A_PtrSize, "UPtr"), "ptr", rot, "Cdecl ptr*") ; enum: IEnumMoniker
		mon := DllCall(NumGet(NumGet(enum+0, "UPtr")+3*A_PtrSize, "UPtr"), "ptr", enum, "uint", 1, "ptr*", mon, "ptr", 0)
        While mon = 0 ; mon: IMoniker
        {
            pname := DllCall(NumGet(NumGet(mon+0, "UPtr")+20*A_PtrSize, "UPtr"), "ptr", mon, "ptr", bindCtx, "ptr", 0, "Cdecl ptr*") ; GetDisplayName
            name := StrGet(pname, "UTF-16")
            DllCall(NumGet(NumGet(malloc+0, "UPtr")+5*A_PtrSize, "UPtr"), "ptr", malloc, "ptr", pname) ; Free
            If InStr(name, Prefix, CaseSensitive) = 1 {
                punk := DllCall(NumGet(NumGet(rot+0, "UPtr")+6*A_PtrSize, "UPtr"), "ptr", rot, "ptr", mon, "Cdecl ptr*") ; GetObject
                ; Wrap the pointer as IDispatch If available, otherwise as IUnknown.
                If (pdsp := ComObjQuery(punk, "{00020400-0000-0000-C000-000000000046}"))
                    obj := ComObject(9, pdsp, 1), ObjRelease(punk)
                Else
                    obj := ComObject(13, punk, 1)
                ; Store it in the Return array by suffix.
                objects[SubStr(name, StrLen(Prefix) + 1)] := obj
            }
            ObjRelease(mon)
        }
        ObjRelease(enum)
        ObjRelease(rot)
        ObjRelease(bindCtx)
        ObjRelease(malloc)
        Return objects
    }
Last edited by BoBo on 19 Aug 2020, 07:43, edited 1 time in total.
Reason: Moved to 'Ask for Help v2'.
User avatar
aseiot
Posts: 63
Joined: 05 Mar 2017, 04:25

Re: GetActiveObjects  Topic is solved

19 Aug 2020, 05:10

Try this:

Code: Select all

GetActiveObjects(Prefix:="", CaseSensitive:=false) {
    objects := Map()
   ,DllCall("ole32\CoGetMalloc", "uint", 1, "ptr*", malloc:=0) ; malloc: IMalloc
   ,DllCall("ole32\CreateBindCtx", "uint", 0, "ptr*", bindCtx:=0) ; bindCtx: IBindCtx
   ,ComCall(8, bindCtx, "ptr*", rot:=0) ; rot: IRunningObjectTable
   ,ComCall(9, rot, "ptr*", enum:=0) ; enum: IEnumMoniker
    while ComCall(3, enum, "uint", 1, "ptr*", mon:=0, "ptr", 0) = 0 ; mon: IMoniker
    {
        ComCall(20, mon, "ptr", bindCtx, "ptr", 0, "ptr*", pname:=0) ; GetDisplayName
      , name := StrGet(pname, "UTF-16")
      , ComCall(5, malloc, "ptr", pname) ; Free
        if InStr(name, Prefix, CaseSensitive) = 1 {
            ComCall(6, rot, "ptr", mon, "ptr*", punk:=0) ; GetObject
            ; Wrap the pointer as IDispatch if available, otherwise as IUnknown.
            if (pdsp := ComObjQuery(punk, "{00020400-0000-0000-C000-000000000046}"))
                ObjAddRef(pdsp.ptr),obj := ComObject(9, pdsp.ptr, 1),ObjRelease(punk)
            else
                obj := ComObject(13, punk, 1)
            ; Store it in the return array by suffix.
            objects[SubStr(name,StrLen(Prefix) + 1)] := obj
        }
        ObjRelease(mon)
    }
    ObjRelease(enum)
   ,ObjRelease(rot)
   ,ObjRelease(bindCtx)
   ,ObjRelease(malloc)
    return objects
}
RNDLDVL
Posts: 15
Joined: 04 Oct 2015, 10:48

Re: GetActiveObjects

19 Aug 2020, 07:41

Code: Select all

        if InStr(name, Prefix, CaseSensitive) = 1 {
I think something about the changes regarding string variables gives me an invalid parameter #2 in this line, which is the Prefix variable. I've tested both v1 and v2, v1 proceeds inside the the if block despite Prefix having a null value which kinda doesn't make sense when you look at it now.

v1:
v2:
swagfag
Posts: 4092
Joined: 11 Jan 2017, 17:59

Re: GetActiveObjects

19 Aug 2020, 07:52

read InStr's remarks about blank needles
RNDLDVL
Posts: 15
Joined: 04 Oct 2015, 10:48

Re: GetActiveObjects

19 Aug 2020, 08:07

swagfag wrote:
19 Aug 2020, 07:52
read InStr's remarks about blank needles
Oh god, I'm stupid. I overlooked that part. Thanks mate, it works fine now.

Here's the code for people interested in COM specifically excel, might be of use.

Code: Select all

GetActiveObjects(Prefix:="", CaseSensitive:=false) {
        objects := Map()
        ,DllCall("ole32\CoGetMalloc", "uint", 1, "ptr*", malloc:=0) ; malloc: IMalloc
        ,DllCall("ole32\CreateBindCtx", "uint", 0, "ptr*", bindCtx:=0) ; bindCtx: IBindCtx
        ,ComCall(8, bindCtx, "ptr*", rot:=0) ; rot: IRunningObjectTable
        ,ComCall(9, rot, "ptr*", enum:=0) ; enum: IEnumMoniker
        while ComCall(3, enum, "uint", 1, "ptr*", mon:=0, "ptr", 0) = 0 ; mon: IMoniker
        {
            ComCall(20, mon, "ptr", bindCtx, "ptr", 0, "ptr*", pname:=0) ; GetDisplayName
            , name := StrGet(pname, "UTF-16")
            , ComCall(5, malloc, "ptr", pname) ; Free
            if (Prefix == "" || InStr(name, Prefix, CaseSensitive) = 1) {
                ComCall(6, rot, "ptr", mon, "ptr*", punk:=0) ; GetObject
                ; Wrap the pointer as IDispatch if available, otherwise as IUnknown.
                if (pdsp := ComObjQuery(punk, "{00020400-0000-0000-C000-000000000046}"))
                    ObjAddRef(pdsp.ptr),obj := ComObject(9, pdsp.ptr, 1),ObjRelease(punk)
                else
                    obj := ComObject(13, punk, 1)
                ; Store it in the return array by suffix.
                objects[SubStr(name,StrLen(Prefix) + 1)] := obj
            }
            ObjRelease(mon)
        }
        ObjRelease(enum)
        ,ObjRelease(rot)
        ,ObjRelease(bindCtx)
        ,ObjRelease(malloc)
        return objects
    }

Return to “AutoHotkey v2 Help”

Who is online

Users browsing this forum: No registered users and 5 guests