COM access to non-Microsoft applications

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
rynsp8
Posts: 46
Joined: 30 Jan 2018, 12:45

COM access to non-Microsoft applications

20 Feb 2018, 11:54

I would like to access COM objects for applications that are not Microsoft Office or standard apps like IE. I assume I could find an API, data-dictionary, or something similar to a software dev kit. But I'm wondering if there is a way to search through the Component Services and find what objects are available. Or, search out a DLL?

-Ryan
User avatar
Xtra
Posts: 2750
Joined: 02 Oct 2015, 12:15

Re: COM access to non-Microsoft applications

20 Feb 2018, 13:15

Take a look here:
GetActiveObjects - Get multiple active COM objects
https://autohotkey.com/boards/viewtopic.php?t=6494
rynsp8
Posts: 46
Joined: 30 Jan 2018, 12:45

Re: COM access to non-Microsoft applications

20 Feb 2018, 14:50

Let's see how this goes.
rynsp8
Posts: 46
Joined: 30 Jan 2018, 12:45

Re: COM access to non-Microsoft applications

20 Feb 2018, 15:41

Xtra, have you seen this work before? I imagine that you have. I'm not sure how the Prefix parameter works out. The application I'm using isn't an office product but is some other software. I imagine that it works something like below, but I certain that I'm wrong:

Code: Select all

activeWindow:= GetActiveObjects(My.Application)

MsgBox %activeWindow


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
}
User avatar
Xtra
Posts: 2750
Joined: 02 Oct 2015, 12:15

Re: COM access to non-Microsoft applications

20 Feb 2018, 16:18

Try using Lexikos' example:

Code: Select all

for name, obj in GetActiveObjects()
    list .= name " -- " ComObjType(obj, "Name") "`n"
MsgBox %list%


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
}
rynsp8
Posts: 46
Joined: 30 Jan 2018, 12:45

Re: COM access to non-Microsoft applications

20 Feb 2018, 16:34

Perhaps I'm not familiar enough with COM to understand what the output of the MsgBox is saying:

I'm seeing a bunch of hexadecimal values and "--INoteLinkContentService"
hexadecimal"--INoteLinkContentService"
!Personal-Monikers::FileSyncClient -- IFileSyncClient9
!Personal-Monikers::SyncEngineCOMServer -- ISyncEngineCOMServer
!Personal-Monikers::SyncEngineStorageProviderHandlerProxy--
!Peronal-Monikers::ToastActivation--
!{hexadecimal}--_Application

I suppose I was expecting COM object output like methods and properties... again perhaps I'm reading this all wrong, or this is the right information that is pointing me to something internal and I just don't understand.
Attachments
snip_20180220163004.png
snip_20180220163004.png (13.23 KiB) Viewed 1850 times
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: COM access to non-Microsoft applications

20 Feb 2018, 17:26

rynsp8 wrote:Perhaps I'm not familiar enough with COM to understand what the output of the MsgBox is saying:

I'm seeing a bunch of hexadecimal values and "--INoteLinkContentService"
hexadecimal"--INoteLinkContentService"
!Personal-Monikers::FileSyncClient -- IFileSyncClient9
!Personal-Monikers::SyncEngineCOMServer -- ISyncEngineCOMServer
!Personal-Monikers::SyncEngineStorageProviderHandlerProxy--
!Peronal-Monikers::ToastActivation--
!{hexadecimal}--_Application

I suppose I was expecting COM object output like methods and properties... again perhaps I'm reading this all wrong, or this is the right information that is pointing me to something internal and I just don't understand.
You are getting a list of every active COM object registered with Windows.

If your application is running and not on that list then it has not registered a COM object and probably does not support COM.

An application developer has to code COM support into their application. It is additional work that most application developers do not do. They have to basically code every method and property of their application they want to expose to other programs. It can be alot of work and some programs do not even want to be controllable by other programs.

Microsoft often does it and other high-end applications like Abode and AutoCAD go through the trouble but other smaller applications do not usually want the coding expense. On the other end, some small one coder applications support it because a real geek is doing the coding and it is not just a time to money calculation in development cost.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
gregster
Posts: 8999
Joined: 30 Sep 2013, 06:48

Re: COM access to non-Microsoft applications

20 Feb 2018, 17:30

But if there is a COM interface, the best way to learn about the methods/properties is to actually look at its documentation, if you don't want to rely on (often unsatisfying) trial and error or plain guessing.

Apart from that, there are sometimes applications where you can add COM support via plugin/add-ons. The music player Foobar is an example, as far as I remember, although the COM support was rather incomplete and wasn't actively developed anymore for some time (but still working last time I tried).
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

Re: COM access to non-Microsoft applications

20 Feb 2018, 17:45

gregster wrote:But if there is a COM interface, the best way to learn about the methods/properties is to actually look at its documentation, if you don't want to rely on (often unsatisfying) trial and error or plain guessing.
That touches on another reason some developers choose not to code COM support, it requires writing a bunch of documentation to go along with the COM support for it to be of much use to others.

Only thing worse than having to write extensive comments in code is writing extensive documentation outside the code... Well other than not doing either and then having to unravel confusing code. But to be honest I actually hate the act of commenting more than unraveling if I had all the time in the world. So I hate commenting / documenting but I have to because I don't have the time not to.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks
User avatar
Xtra
Posts: 2750
Joined: 02 Oct 2015, 12:15

Re: COM access to non-Microsoft applications

26 Feb 2018, 12:31

Doing a search for "ISyncEngineCOMServer api"

This web page shows what documentation looks like:
http://docs.rhomobile.com/en/2.2.0/rhod ... ngine-api/

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Google [Bot], prototype_zero and 241 guests