Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

COM QueryInterface


  • Please log in to reply
46 replies to this topic
  • Guests
  • Last active:
  • Joined: --
What is it? I've read this page but have no ideas what it is talking about. I'd like to be able to manipulate IShellLink methods and am guessing it might be related to COM QueryInterface. Is the ComObjQuery() function something to do with it?

Could somebody give an example that demonstrates what it does? The manual examples for ComObjQuery is too complicated to understand for me. Thanks.

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

Could somebody give an example that demonstrates what it does?

This example uses the Acc Library:
IID := "{332C4427-26CB-11D0-B483-00C04FD90119}" ; IHTMLWindow2 GUID

Run, iexplore.exe http://www.autohotkey.com/forum/
MsgBox, 262144, , Click OK once the webpage is loaded ...

ControlGet, hwnd, hwnd, , Internet Explorer_Server1, ahk_class IEFrame

AccObject := Acc_ObjectFromWindow(hwnd) ; Access the IAccessible Interface

ptr := ComObjQuery(AccObject, IID, IID) ; Query for the IHTMLWindow2 Interface
Window := ComObjEnwrap(ptr) ; Wrap the pointer so we can use it
ObjRelease(ptr) ; Release the pointer

MsgBox, , Online Users Info, % Window.Document.all(243).innerText


  • Guests
  • Last active:
  • Joined: --
Thanks, jethrow, for the example. [*:2pmhaz0a]Is the point of the ComObjQuery() function to connect with an existing COM object? [*:2pmhaz0a]I'm I on the right path by learning to use the ComObjQuery() function in order to use the IShellLink interface?[*:2pmhaz0a]Where did you find this value, {332C4427-26CB-11D0-B483-00C04FD90119}?By the way, I found a tutorial. http://www.autohotke...erface_tutorial

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
[*:gt3aqldn]yes[*:gt3aqldn]you may need it[*:gt3aqldn]OLE/COM Object Viewer - Interfaces

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011

By the way, I found a tutorial. <!-- m -->http://www.autohotke... ... e_tutorial<!-- m -->

8)

A question: What do you think you'll need ComObjQuery() for?

A long time ago I also started writing an IShellLink wrapper. Here are my efforts (very poor :)):
class IShellLink extends IUnknown
	{
	static CLSID := "{00021401-0000-0000-C000-000000000046}"
	static IID := "{000214F9-0000-0000-C000-000000000046}"
	
	GetPath(){
		
		}
		
	GetIDList(ByRef idlist){
		return DllCall(NumGet(this.vt+04*A_PtrSize), "Ptr", this.ptr, "Ptr", idlist)
		}
	
	SetIDList(idlist){
		return DllCall(NumGet(this.vt+05*A_PtrSize), "Ptr", this.ptr, "Ptr", idlist)
		}
		
	GetDescription(){
		
		}
		
	SetDescription(description){
		return DllCall(NumGet(this.vt+07*A_PtrSize), "Ptr", this.ptr, "str", description)
		}
		
	GetWorkingDirectory(ByRef directory){
		return DllCall(NumGet(this.vt+08*A_PtrSize), "Ptr", this.ptr, "str", directory, "Int", 0)
		}
		
	SetWorkingDirectory(directory){
		return DllCall(NumGet(this.vt+09*A_PtrSize), "Ptr", this.ptr, "str", directory)
		}
		
	GetArguments(ByRef arguments){
		return DllCall(NumGet(this.vt+10*A_PtrSize), "Ptr", this.ptr, "str", arguments, "Int", 0)
		}
		
	SetArguments(arguments){
		return DllCall(NumGet(this.vt+11*A_PtrSize), "Ptr", this.ptr, "str", arguments)
		}
		
	GetHotkey(ByRef hotkey){
		return DllCall(NumGet(this.vt+12*A_PtrSize), "Ptr", this.ptr, "Int", hotkey)
		}
		
	SetHotkey(hotkey){
		return DllCall(NumGet(this.vt+13*A_PtrSize), "Ptr", this.ptr, "Int", hotkey)
		}
		
	GetShowCmd(ByRef ishowcmd){
		return DllCall(NumGet(this.vt+14*A_PtrSize), "Ptr", this.ptr, "int", ishowcmd)
		}
	
	SetShowCmd(ishowcmd){
		return DllCall(NumGet(this.vt+15*A_PtrSize), "Ptr", this.ptr, "int", ishowcmd)
		}
		
	GetIconLocation(ByRef path, ByRef iconnr){
		return DllCall(NumGet(this.vt+16*A_PtrSize), "Ptr", this.ptr, "str", path, "int", 0, "int", iconnr)
		}
		
	SetIconLocation(path, iconnr){
		return DllCall(NumGet(this.vt+17*A_PtrSize), "Ptr", this.ptr, "str", path, "int", iconnr)
		}
		
	SetRelativePath(path){
		return DllCall(NumGet(this.vt+18*A_PtrSize), "Ptr", this.ptr, "str", path, "uint", 0)
		}
	
	Resolve(){
		
		}
		
	SetPath(path){
		return DllCall(NumGet(this.vt+20*A_PtrSize), "Ptr", this.ptr, "str", path)
		}
	
	}
May I ask you to write a wrapper comforming to CCF :?:
If you need any help, I'd be happy to help you ;-)

Regards
maul.esel

Edit: I just corrected the wiki link to the newer tutorial version. Find it here. In case you have / want to create an account, feel free to PM me.
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

  • Guests
  • Last active:
  • Joined: --

[*:35yfz5vr]OLE/COM Object Viewer - Interfaces

Thanks. Does that mean if I use one of the listed IDs and if the script user's OS doesn't have it, the code doesn't work in the user's environment?

browsing through msdn, you will find many information pointing to COM interfaces.
If you know object oriented programming, you know that interfaces define what functions (or fields etc.) a class must include.

So does a COM interface mean something like a class variable in AutoHotkey? In the following code, MyClass define methods and properties. In this page, there is a list of Shell Interfaces and can I think them like the COM version of class variables already defined by Windows?
oMyClass := new MyClass

oMyClass.MyMethodA()
oMyClass.MyMethodB("hello")

Class MyClass {
   
    MyProperty := "hi"

    MyMethodA() {
        msgbox % this.MyProperty
    }
	MyMethodB(param) {
		msgbox % param
	}
}

A question: What do you think you'll need ComObjQuery() for?

Thanks for the supportive response. jethrow answered my question:

Is the point of the ComObjQuery() function to connect with an existing COM object?

yes

But I'm not sure why it's required to connect with an existing COM object in order to use those Shell interfaces. Maybe have they already been instantiated by Windows so that user scripts only need to access them without instantiation?

A long time ago I also started writing an IShellLink wrapper. Here are my efforts

I'm still struggling to figure out how to use it. I downloaded this and am trying to find which file is needed to use the ShellLink interface. I'm guessing I need unknown.ahk. By the way, why are the methods, GetPath(), GetDescription(), and Resolve() left empty in the code posted your reply?

May I ask you to write a wrapper comforming to CCF :?:

I haven't gotton the whole picture of your project, so unless I get a clear picture, probably I'm not able to.

Edit: I just corrected the wiki link to the newer tutorial version. Find it here. In case you have / want to create an account, feel free to PM me.

English is not my native language, so sorry, I'm not inclined to edit Wiki pages.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

So does a COM interface mean something like a class variable in AutoHotkey?

"Class variable" typically means a variable defined within a class. What you're thinking of is probably just a class. In AutoHotkey, a class defines a collection of methods and variables, but the concept is a more general one. A class in AutoHotkey or virtually any other language is somewhat like an interface plus an implementation of an interface.

Further reading:
MSDN: Interfaces and Interface Implementations
MSDN: The Component Object Model

Is the point of the ComObjQuery() function to connect with an existing COM object?

I think this question could be taken any number of ways, mostly vague, so a yes/no answer is useless. The point of ComObjQuery is to retrieve a particular interface of an object. To understand what that means, you need to first learn what an interface is (or more fundamentally, how function calls work in a compiled language).

All objects which can be used naturally by scripts implement a specific interface, which basically allows AutoHotkey to "describe" which function it wants to call and what the types and values of each parameters are. Other objects can only be operated through more specific interfaces which AutoHotkey doesn't natively understand, like any function you would call via DllCall. Understanding why ComObjQuery is needed is only the first step; working out how to call an interface method via DllCall is somewhat more complicated.

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011
Hi :)

Does that mean if I use one of the listed IDs and if the script user's OS doesn't have it, the code doesn't work in the user's environment?

Yes. Usually the required OS is noted on the interface's msdn page.

So does a COM interface mean something like a class variable in AutoHotkey? In the following code, MyClass define methods and properties. In this page, there is a list of Shell Interfaces and can I think them like the COM version of class variables already defined by Windows?

Lexikos already answered that question. To put it simply, the IShellLink + a lot of other interfaces are implemented by Windows classes. In your wrapper, you simply call these classes' methods.

jethrow answered my question: ...

you may need it

And I'm asking what you would it need for? Because I really doubt you need it for IShellLink. I'd say you need ComObjCreate() for creating an instance, and then DllCall() for calling the functions as shown in my tutorial.

I'm still struggling to figure out how to use it. I downloaded this and am trying to find which file is needed to use the ShellLink interface. I'm guessing I need unknown.ahk.

You don't really need it unless you're going to write code for CCF.

By the way, why are the methods, GetPath(), GetDescription(), and Resolve() left empty in the code posted your reply?

Because the implementation isn't finished at all ;-)

I haven't gotton the whole picture of your project, so unless I get a clear picture, probably I'm not able to.

I'd say in case you have an idea how to use AHK classes (as you have shown) it's easier with than without the CCF.
CCF defines some useful base and helper classes for COM interface wrappers + some standardization rules. If you need more info, email/PM me or post in the CCF thread.

English is not my native language, so sorry, I'm not inclined to edit Wiki pages.

Well, actually I said I edited the page ;-) English isn't my native language either. What is yours? Maybe we could communicate that way? German? French?

Regards
maul.esel
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

  • Guests
  • Last active:
  • Joined: --

"Class variable" typically means a variable defined within a class. What you're thinking of is probably just a class. In AutoHotkey, a class defines a collection of methods and variables, but the concept is a more general one. A class in AutoHotkey or virtually any other language is somewhat like an interface plus an implementation of an interface.

So a COM interface is like a class without implementation of an interface. Sounds like it is a prototype.

Further reading:
MSDN: Interfaces and Interface Implementations
MSDN: The Component Object Model

Thanks for the links. I've tried read them but to be honest, I have no idea what is talked about. Probably it takes time.

I think this question could be taken any number of ways, mostly vague, so a yes/no answer is useless. The point of ComObjQuery is to retrieve a particular interface of an object.
...
...
All objects which can be used naturally by scripts imlement a specific interface, which basically allows AutoHotkey to "describe" which function it wants to call and what the types and values of each parameters are. Other objects can only be operated through more specific interfaces which AutoHotkey doesn't natively understand, like any function you would call via DllCall.

So ComObjQuery() is like a COM version of RegisterCallBack() which returns a machine-code memory address of a function, isn't' it? ComObjQuery returns the pointer of a specified COM interface and RegisterCallBack returns a memory address of a specified function.

To understand what that means, you need to first learn what an interface is (or more fundamentally, how function calls work in a compiled language).

Thanks for the advise. In fact, I don't understand the concept of COM interfaces and it is not defined in the manual. Probably it takes time too.

Understanding why ComObjQuery is needed is only the first step; working out how to call an interface method via DllCall is somewhat more complicated.

Thanks for ensuring that this is complicated. I'm always frustrated by seeing some saying AutoHotkey is easy while I've never seen them answering these complicated concepts.

Yes. Usually the required OS is noted on the interface's msdn page.

I see. I get different values from yours for IShellLinkW with OLE/COM Object Viewer. The CLSID value is different than what you posted.

Interface =
{000214F9-0000-0000-C000-000000000046} = IShellLinkW
CLSID =
{C90250F3-4D7D0-4991-9B69-A5C5BC1C2AE6} = PSFactoryBuffer

To put it simply, the IShellLink + a lot of other interfaces are implemented by Windows classes. In your wrapper, you simply call these classes' methods.

OK, I don't understand why it's possible to query an non-instantiated object.

And I'm asking what you would it need for? Because I really doubt you need it for IShellLink. I'd say you need ComObjCreate() for creating an instance, and then DllCall() for calling the functions as shown in my tutorial.

I have no idea. I need to use IShellLink. I tried the tutorial but it didn't have a working example so I couldn't fully understand the process. In the last part, it suddenly introduces how it could be written in Class and I could not find how I can use it. Now I'm trying to find how it works examining the files I downloaded. The files have some examples but even one example has seveal include files so I'm kind of giving up at this point.

You don't really need it unless you're going to write code for CCF.

So what do I need for IShellLink? Probably basic understanding of ComObjQuery() is required, isn't it? I've been struggling to figure it out for three days by now.

I'd say in case you have an idea how to use AHK classes (as you have shown) it's easier with than without the CCF.
CCF defines some useful base and helper classes for COM interface wrappers + some standardization rules. If you need more info, email/PM me or post in the CCF thread.

I think what I need first is very simple working examples of COM interface usages in AHK. After examining and observing them and get a basic understanding of that it does, then I can move on to some complicated tasks.

Well, actually I said I edited the page ;-) English isn't my native language either. What is yours? Maybe we could communicate that way? German? French?

It's neither of them. There isn't an established community in my language. So don 't worry about it.

Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

OK, I don't understand why it's possible to query an non-instantiated object.

It isn't. ComObjQuery's first parameter is an instance of an object.

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011

So a COM interface is like a class without implementation of an interface. Sounds like it is a prototype.

Nonsense. A COM interface is an interface. But in case of IShellLink, Windows provides the "ShellLink" class, which is an implementation of IShellLink.

So ComObjQuery() is like a COM version of RegisterCallBack() which returns a machine-code memory address of a function, isn't' it? ComObjQuery returns the pointer of a specified COM interface and RegisterCallBack returns a memory address of a specified function.

Not really. You give it an instance of a class. And if this class implements the specified interface, it'll give you a pointer to the vTable (a memory table with function pointers and more, see my tut). ComObjQuery() just calls the instance's QueryInterface() method (which all COM interfaces have).

In fact, I don't understand the concept of COM interfaces and it is not defined in the manual.

This is because it's not really an AHK but a Windows / platform topic. And as such, it is e.g. explained in the msdn (much more complex than the AHK manual of course ;-))

I'm always frustrated by seeing some saying AutoHotkey is easy while I've never seen them answering these complicated concepts.

Now can you see me? ;-) Essentially this is the same as above.

I get different values from yours for IShellLinkW with OLE/COM Object Viewer. The CLSID value is different than what you posted.

First of all, I didn't post it :) Looking in the Windows SDK:
IID_IShellLinkW := "{000214F9-0000-0000-C000-000000000046}"
IID_IShellLinkA := "{000214EE-0000-0000-C000-000000000046}"

#ifdef UNICODE
#define IShellLink      IShellLinkW
#else
#define IShellLink      IShellLinkA
#endif

CLSID_ShellLink := "{00021401-0000-0000-C000-000000000046}"
The IID jethrow posted was the one for IHTMLWindow2 as he wrote in his code

As I said, for any problems with the CCF / the tutorial, please ask me and I'll try to answer you as well as improve the tutorial. Did you look at the newer version linked at the top of the wiki page?

Probably basic understanding of ComObjQuery() is required, isn't it?

Did you read anythin I posted? What the hell do you need ComObjQuery() for???

I'd say you need ComObjCreate() for creating an instance, and then DllCall() for calling the functions as shown in my tutorial.


I think what I need first is very simple working examples of COM interface usages in AHK. After examining and observing them and get a basic understanding of that it does, then I can move on to some complicated tasks.

OK. IMO, there's enough in the tutorial, but here you are:
link := ComObjCreate(CLSID_ShellLink, IID_IShellLinkA) ; create an instance (uses the stuff defined above)
DllCall(NumGet(NumGet(link + 0)+20*A_PtrSize), "ptr", link, "str", "C:\tst.txt") ; call the SetPath() method
; SetPath() is the 21st method for the interface (QueryInterface = 0, AddRef = 1, Release = 2, GetPath = 3 , ..., Resolve = 19, SetPath = 20)
; the 1st argument is the instance (explained in the tut)
; the 2nd argument is the actual path argument
; NumGet(link + 0) gets the pointer to the vTable
; NumGet(NumGet(link + 0) + 20 * A_PtrSize) gets the function pointer to the 21st method in this table

Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011
OK, I got some time. I started an IShellLinkW implementation for CCF. View it here (should work with AHK_L 1.1+ both Unicode and ANSI, not tested though).

Now that I really looked into it I have an idea what you'd need QueryInterface() for (I didn't have an idea before because you refused to tell me :?). In case you're trying to save the instance to a file, that's indeed something for QueryInterface(). I'll look if I have some more time I'll add an IPersistFile wrapper class + write an example for saving the link to a file.

In case this is not what you want, explain what you're actually trying to do.

Regards
maul.esel
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

-
  • Guests
  • Last active:
  • Joined: --

You give it an instance of a class.

Technically, you give it an interface pointer.

A COM wrapper object or raw interface pointer.



  • Guests
  • Last active:
  • Joined: --

This is because it's not really an AHK but a Windows / platform topic. And as such, it is e.g. explained in the msdn (much more complex than the AHK manual of course ;-))

If you say, it is difficult because the material that the coder is trying to deal with is difficult not AHK itself, then AHK has never been easy for anything, but the material was easy. This is irrelevant to the question.

Now can you see me? ;-) Essentially this is the same as above.

What do I see you for? If you are providing solutions for complicated tasks, you are not one of them.

First of all, I didn't post it :) Looking in the Windows SDK:

IID_IShellLinkW := "{000214F9-0000-0000-C000-000000000046}"
IID_IShellLinkA := "{000214EE-0000-0000-C000-000000000046}"

#ifdef UNICODE
#define IShellLink      IShellLinkW
#else
#define IShellLink      IShellLinkA
#endif

CLSID_ShellLink := "{00021401-0000-0000-C000-000000000046}"

The IID jethrow posted was the one for IHTMLWindow2 as he wrote in his code

The code doesn't look like for AutoHotkey. So where in OLE/COM Object Viewer do I need to refer to for CLSID and GUID? I don't find this number, 00021401-0000-0000-C000-000000000046. Here is the screenshot. This is what I see Posted Image

...if you have the Windows SDK, check the header file. It is named on the bottom of the msdn page: Header: Shobjidl.h. Open that file and search for ITaskbarList, scroll down until you find something like

OK, I downloaded Microsoft Windows SDK v7.1 and do I use Windows SDK 7.1 Command Prompt? It bundles several tools and there is GUID Generator. I couldn't figure out how to use this either. So for the IShellLink interface, do I check the header of Shell32.dll? I've never opened a dill file.

maul.esel
As I said, for any problems with the CCF / the tutorial, please ask me and I'll try to answer you as well as improve the tutorial. Did you look at the newer version linked at the top of the wiki page?

Unless I understand the difference on issues between ComObjQuery() and CCD/the tutorial, I won't be able to correctly decide which thread I should post my questions.

Did you read anythin I posted? What the hell do you need ComObjQuery() for???

I said I have no idea. If ComObjQuery() is not needed in order to use the ISHellLink interface, I don't need to use ComObjQuery(). Can you tell what exactly I need to use the IShellLink interface?

IMO, there's enough in the tutorial, but here you are:

link := ComObjCreate(CLSID_ShellLink, IID_IShellLinkA) ; create an instance (uses the stuff defined above)
DllCall(NumGet(NumGet(link + 0)+20*A_PtrSize), "ptr", link, "str", "C:\tst.txt") ; call the SetPath() method
; SetPath() is the 21st method for the interface (QueryInterface = 0, AddRef = 1, Release = 2, GetPath = 3 , ..., Resolve = 19, SetPath = 20)
; the 1st argument is the instance (explained in the tut)
; the 2nd argument is the actual path argument
; NumGet(link + 0) gets the pointer to the vTable
; NumGet(NumGet(link + 0) + 20 * A_PtrSize) gets the function pointer to the 21st method in this table

It isn't a working example. A working example should be able to demonstrate what it does; it needs a result something like what happened and what changed and how the code is related to the result.

In addition, you say the SetPath method is the 21st method. It is mentioned in the tutorial to use this web site in order to find out the order of the functions. It says that the first three methods are inherited by the IUnknown interface. Indeed, Win32 Programmer's Reference lists the first three methods as IUnknown. So I'm guessing that SetPath is the 18th method in the IShellLinkW interface. Therefore, shouldn't it be NumGet(link + 0)+17*A_PtrSize?

Also Is it the only way we can do to use Win32 Programmer's Reference to find out which nth number is applied to which method in Vtable? The web side doesn't seem to distinguish between IShellLinkA and IShellLinkW. Are they both the same?

I started an IShellLinkW implementation for CCF. View it here (should work with AHK_L 1.1+ both Unicode and ANSI, not tested though).

Nice, but there aren't examples for it. So I'm not able to use it.

Now that I really looked into it I have an idea what you'd need QueryInterface() for (I didn't have an idea before because you refused to tell me :?). In case you're trying to save the instance to a file, that's indeed something for QueryInterface().

Now you are talking about something new to me. Do you mean ComObjQuery() by saying QueryInterface()? To make it as clear as possible, I need to use the IShellLink interface and simple working examples of it in order to understand how I can use it. If this is not related to COM QueryInterface, please tell me so. In that case, I'll create another thread.

In case this is not what you want, explain what you're actually trying to do.

First of all I must say, thank you maul.esel for all the patiance you have so far. What I'm looking for is an instruction for the IShellLink interface usage in AutoHotkey. Hopefully, it reads the target path of a specified lnk file and detect the icon location of it.

If this topic became too complicated, please focus on the underlined part.

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

This is because it's not really an AHK but a Windows / platform topic. And as such, it is e.g. explained in the msdn (much more complex than the AHK manual of course ;-))

If you say, it is difficult because the material that the coder is trying to deal with is difficult not AHK itself, then AHK has never been easy for anything, but the material was easy.

You must realize, AHK is designed to streamline/simplify common Windows Automation tasks. These tasks are not easy, but AHK is essentially a wrapper to make it easy for the user. However, AHK is not designed for the task you are trying to accomplish - though it does provide the means to accomplish it. Perhaps you are the one who is supposed to write the code to make all this easy ...


...if you have the Windows SDK, check the header file. It is named on the bottom of the msdn page: Header: Shobjidl.h. Open that file and search for ITaskbarList, scroll down until you find something like

Personally, I like this page. Just find your header file on the side and click to bring it up. Search for typedef struct InterfaceNameVtbl to get the Virtual Table, or IID_InterfaceName to get the IID. (in this case it would be typedef struct IShellLinkWVtbl & IID_IShellLinkW)