I know I can read the CLSID from a COM class object in the registry from Classes\<CLASSNAME>\CLSID\#.
I suspect on a registered COM interface I can read up the IID from Classes\<CLASSNAME>\IID\# or Classes\CLSID\<CLSID>\IID.
I've read the article COM IDs & Registry keys in a nutshell and this question is still open to me. Unfortunately, I have no test case right now.
The registry was not meant to be a programming resource, registry entries are only there when the COM infrastructure needs them. The CLSID key for example is necessary to help COM find the executable file that implements a server, the programmer has to supply the CLSID guid.
He needs to know the IID as well, passes it to QueryInterface() to obtain the interface pointer. There might be an entry in HKLM\Software\Classes\Interface but it isn't terribly common. The COM infrastructure needs it when an interface needs to be marshaled from one apartment to another, the registry key contains the CLSID of the proxy that helps to get that job done. A quick look with Regedit.exe in that key ought to convince you that it isn't likely to be helpful at all, there is no connection whatsoever with the server itself. Only if you are very lucky might you find a Type library LIBID there.
There are two basic ways that the COM programmer supplies you with CLSID and IID values. The unfriendly way is an .idl or .h file, several Windows components (DirectX, Media Foundation, WASAPI, etc) are like that. Good enough to see the IIDs back.
The friendly way is a type library, a language-independent description of the implemented coclasses and interfaces that just about any compiler knows how to read. Sometimes supplied as separate .tlb or .olb file but usually embedded as a resource in the executable file. Best way to have a look at it is with the Oleview.exe SDK utility. Use File > View Typelib and select the .tlb or .dll file. It decompiles the type library back into IDL, the language that a COM author uses to describe his component. You'll have no trouble finding the IIDs back. Only thing you have to know is the name of the executable file.
Be sure to take advantage of the type library in your compiler, assuming you found one. You can now use friendly names instead of raw GUIDs, get syntax checking on your code and rarely have to do anything dramatic when the version changes and the author properly used new IIDs. Be sure to talk to the author if you can't find one, a small hint can save you an enormous amount of trouble.
Related
I'm looking for a missing COM interface X which I suspect is defined in Y.dll. I can peek at this presumptive interface using
grep X Y.dll
which says "matches". Hurrah, suspicion confirmed!
Alas, when I use the Object Browser in Visual Studio Express, trying to add Y.dll to my Custom Component Set, I get the error: "Some components could not be browsed" in a pop-up window.
So what are the reasons I can't browse this dll? Can the COM interfaces deliberately or accidentally be protected, hidden, secured, or obscured? Obviously I need a primer!
Officially, all Microsoft knows about this seems to be generally devoid of insight:
This error generally occurs when you attempt to add a file type that does not support object browsing, such as .htm
and .txt files, in the Component Selector dialog box. The Object Browser supports file types such as .bsc, .olb,
.tlb, .dll, .exe, and .ocx.
Seriously, what are the reasons for a dll or exe to not support object browsing? Any pointers to tutorials or books would be appreciated by this beginner! Thanks.
COM Object browsers rely on metadata (type libraries) exported by COM servers (dll, exe, ocx, etc).
The problem is that COM Servers are not required to export any metadata about which interfaces it implements. Unfortunately I have found quite a number of such servers (so one needs to know which CoClasses, Interfaces, etc are supported by other means).
Check if your COM Server (y.dll) contains a resource called "TYPELIB" similar to:
Hope this helps.
How do you call IFileOpenDialog and IFileSaveDialog from VBA?
According to Microsoft, applications written for Windows 7 and later should use IFileOpenDialog/IFileSaveDialog API calls instead of GetOpenFileName/GetSaveFileName (see Using the Common File Dialog). This is especially important for full Library support.
Short answer: it's probably not worth the effort.
Longer answer: the CFD interfaces don't extend IDispatch, which makes them impossible to call via late binding from VBA. That doesn't mean they can't be called from VBA, but it means they require a typelib to describe the "shape" of the IUnknown-based CFD interfaces. Unfortunately, Microsoft doesn't provide the CFD interface definitions in a typelib. You can roll your own typelib by reverse-engineering the header files (or try to find the original IDL in the SDK), but you'd then have to register that typelib on every machine you want to use it on (the tools for which are not shipped on the machine, unlike regsvr32 for COM stuff). Assuming you did all that, you could then reference the typelib from VBA, and conditionally call it on Vista or higher OSes. You could also shim through to a small .NET assembly that would create a System.Windows.Forms.FileDialog-derived type and marshal the results back to VBA- that would be much easier, but still more-or-less require that you register the assembly on every machine (or use C++/CLI or other hacks to export a managed DLL function), and it requires you to take a .NET dependency.
They sure didn't make it easy... :) Good luck!
Which WinAPI method or interface I can use to enumerate the interfaces, properties, methods(and parameters) of a COM Object programmatically?
You need to be more specific. There are two ways to interpret your question.
One is that you have a COM component (e.g. some library), and you want to programmatically enumerate interfaces/properties/methods of that. Usually (but not always), COM components come with a type library that contains full metainformation about all this - it's either embedded into the COM .exe or .dll, or is a separate .tlb file. In any case, if the COM component is properly registered in the system (e.g. using regsvr32), then COM provides a standard API to retrieve that type information, centered around ITypeLib and ITypeInfo interfaces.
Another interpretation is that you get a reference to a particular COM object, and you need to enumerate all methods/properties on that and/or invoke them by computed name, like Java or C# reflection, or Delphi RTTI. If so, then it is only possible if the COM object implements IDispatch interface, which allows you to do all of the above.
Well, COM objects are referenced through interfaces, which are opaque abstractions by design. You can't get at the underlying object without some black magic that will only work if you have a really good knowledge of the low-level details of the Delphi object model and the object was actually written in Delphi.
About the best you can do is examine the interface declaration itself, which will give you all the available information in its methods and properties.
I assume you want a list of all interfaces that will successfully QueryInterface. The answer is there's no intrinsic way in COM to do this. Some interfaces themselves provide this functionality like IServiceProvider.
You can get at everything you want from the registry, however this will take some time as the information is not ordered in such a way to give you the information you want without first analyzing most of it. If you download the utility OLEVIEW32 from the Microsoft platform SDK (available on MSDN) you can use it to explore the COM interfaces registered on the machine.
The fundamentals of COM work through the interfaces registered in the registry, under the HKEY CLASSES ROOT\CLSID. When you ask for a specific com object, it resolves to one of these guids, which in turn looks at the InprocServer32 section under this guid to determine what DLL/EXE to load, and what threading model to use. You could use this information to build a map of guids which also resolve to the same DLL (this is to get the classes)
In HKEY CLASSES ROOT\Interface is a link to all of the interfaces registered in the system. Again, its time to play lookup since much of this information is just pointers to another key, or type library. What IS here however and is useful is a list of GUID -> InterfaceName (default property of each guid).
In HKEY CLASSES ROOT\TypeLib is a link to all of the type libraries registered in the system.
How do I reference and communciate with an ActiveX library from within my gcc compiled application?
Well, I've never actually tried it, but there is no reason you wouldn't be able to do this. You basically just need to have the interface definitions for the classes you need (might be able to get this from VS) and then make the appropriate calls.
The function CoCreateInstance is in Ole32.dll, so you could probably load the library, get the entrypoint, and then you just have to find the CLSIDs for creating the COM object you want, etc. As long as you are careful about only casting with QueryInterface, you should be just fine; COM was designed specifically to provide binary compatibility so that this would be possible.
http://msdn.microsoft.com/en-us/library/ms686615%28VS.85%29.aspx
the hardest part will be getting all the headers and such that you need.
We are using a COM Object automation model to make our application available to our customers.
They are using for the most part python to access our applicaton interface.
As we want to be able to install (not yet run, that's another issue) different versions of the application, we are changing our COM components to be regfree.
But that conflicts with the access from scripting languages through IDispatch automation since they need the entries in the registry.
Our approach is to create an application which manages the active version of our actual application. It lets the user decide which version he wants to have and it takes care of the registry entries.
What are the alternatives to our approach?
There is a protocol within COM for doing this. If you version the Interfaces (and change the GUIDS for each version) you can install multiple versions. Microsoft does this with WORD etc.
It is possible to create a Word.Document.5 class which is specific to version 5 of the library, or just word.Document which will create an instance of the highest present on the machine. I'm not sure if this functionality is build into COM or needs to be impemented but it's worth looking into.
Regfree COM objects can be accessed through the Microsoft.Windows.ActCtx object.
As for IDispatch automation requiring entries in the registry -- that's not strictly correct. I presume you're using the default ATL implementation, IDispatchImpl.
We solved this solution by providing our own implementation, IRegFreeDispatchImpl, which used the activation context manipulation APIs in the manner suggested here to wrap all entry points into the DLL with an activation context activation/deactivation.
Well the answer is suggested by yourself. You can write an application which has complete list of all versions of COM components. Once a version is selected by user, you can call regsvr32 application to register that particular version.