MSDN:
"You implement an IClassFactory interface for each (COM) class of object that you offer to be instantiated."
Is it useful to create COM class without Class Factory?
The IClassFactory is provided for objects which are instantiated directly by the caller, for example using CreateObject or CoCreateInstance, or GetObject.
Other objects can be obtained by getting them indirectly from objects that are created.
For example, the Scripting.FileSystemObject in VB or VBScript is created directly. You can use the methods to obtain File or Folder objects, which cannot be directly created. Instead these are created by the FileSystemObject and returned from FileSystemObject methods.
Is it useful to create COM class without Class Factory?
Yes, why not? It can still be fully featured COM class, just except that you cannot launch it via CoCreateInstance API. For some reason you might want to make it available otherwise, e.g. as a returned [out] parameter on a method of another interface/class, or via GetActiveObject API.
Class factories let you expose your class for direct instantiation.
I'm not entirely sure the wording is quite correct here. You almost always implement IClassFactory once for all COM classes of objects that your host will instantiate. In particular, your implementation of IClassFactory is what gets returned from DllGetClassObject.
In particular, when someone calls CoCreateInstance(CLSID_foo, pUnkOuter, CLSCTX_INPROC, IID_IFoo, (void **) &pFoo), the following things happen (assuming you're not doing remoting):
COM looks up CLSID_foo in the registry. (In particular, HKEY_CLASSES_ROOT\CLSID\\InprocServer32).
COM loads that DLL and calls DllGetClassObject with IID_IClassFactory.
Your DLL returns a function pointer to the implementation of IClassFactory.
COM calls your implementation of IClassFactory::CreateInstance with pUnkOuter, IID_IFoo, and pFoo.
There are many other situations where you would have COM objects that aren't directly creatable, as #Ben mentioned. There are even other standard factory interfaces, like IServiceProvider, that exist so that classes can expose a dynamic set of interfaces.
I'd like to have a managed com object that exposes methods which accept as arguments objects implementing given interfaces. Something like this
[ComVisible(true)]
[Guid(".....")]
class SomeClass {
public void SomeMethod(ISomeInterface arg)
.....
Apparently ISomeInterface should also be declared ComVisible.
Now I want to consume that COM object in a managed client and call SomeMethod there. The problem is I need to instantiate an object that implements ISomeInterface. If that was a native COM object I'd get an interop assembly generated automatically and that won't be a problem. One cannot generate an interop assembly for managed COM object though.
I see that .NET 4.0 introduces the type equivalence concept. It looks like I could generate an interop manually using the ComImport attribute. But that looks like a pretty nasty job. I guess I could also use the TypeIdentifierAttribute but the documentation on that is vague and it says it's mostly intended for use by compilers.
So are there any other ways to do that?
I've implemented a windows deskband (using the windows SDK sample) and need a way to communicate (one call to start IPC with another application, IPC is already working) with it.
My COM experience is very limited but extrapolating from what I've seen, I think it should be possible to create a new COM interface, implement it in the deskband object (which I have access to via IBandSite), call QueryInterface() for my own interface on it and then use it to call directly into the deskband.
I've tried this but ran into problems very quickly (main reason being: I've no idea what I'm actually doing most of the time ...)
So, my questions are: Is this a viable approach and can someone give me an outline on how to proceed if it is (or point to some resource that could be helpful - short of reading a COM book, which would be my last approach). If it is not, do alternatives come to mind ?
Thank you for your time and best wishes,
Rene.
Here's you path: you add a new interface into .idl file and also if you have a co-class in the .idl file that corresponds to you COM object you list that new interface in the co-class definition. Then you compile the .idl and this gets you a .h file and a .c file with identifiers - the C++ IID and C++ interface definition.
Then you inherit your COM object C++ class from the C++ interface and implement all methods of it. If for whatever reason you can't or don't want to implement a method you have to return E_NOTIMPL from that method implementation.
One very important final thing: you have to change QueryInterface() behavior in you COM object class. If you use ATL you have to add an entry into the COM map. If you don't use ATL change you QueryInterface() - see this question for how to implement QueryInterface() in case of implementing several COM interfaces.
I searched hard, but was unable to grasp the whole idea. Can anyone tell me:
What COM actually is?
How do GUIDs work, and how are they used by COM?
How does COM resolve the issues of different DLL versions.
Or at least, point me to a good article somewhere that explains these concepts?
Thanks!
COM is "Component Object Model". It is one of the first technologies designed to allow "binary reuse" of components... Originally, it was the rewrite of what was, in Microsoft Office circa 1988-1992 time frame, referred to as Dynamic Data Exchange (DDE), a technology designed to allow the various Office applications to talk to one another. The first attempt to rewrite it was called OLE-Automation (Object Linking and Embedding). But when they got done they renamed it to COM.
How it works:
Essentially, before COM, when a client component wanted to use a component (written as a C++ library), it had to be compiled WITH the library, so it could know exactly how many bytes into the compiled binary file to find each method or function call.
With COM, there is a defined mechanism as to how these methods will be structured, and then the compiler produces a separate file (called a type library or an Interface Definition Language (IDL) file, that contains all this function offset data.
Then, as a user of the component, you have to "register" it, which writes all this information (Keyed off of GUIDs) into the OS Registry, where any client app can access it, and by reading the data from the registry, it can know where in the binary file to find each method or class entry point.
Your question is a little large for a full explanation here. A quick high-level introduction to COM can be found in the book Understanding ActiveX and OLE. A more detailed but still introductory introduction is Inside COM. The best book on the subject is Don Box's Essential COM.
A couple of quick answers:
COM is a binary interface standard for objects. It allows various programs to write to interfaces without all having to have been written in the same langauge with the same compiler. There are also related services available.
GUIDs are globally unique numbers that COM uses to identify interfaces.
COM doesn't resolve different DLL version problems. It only allows a single DLL to be registered for each GUID.
COM enables reusable software. Like building blocks, you can create COM objects (or now Assemblies in .NET) to provide functionality to a larger piece of software. I have used COM to provide DB integration for Excel and MS BizTalk. Software like MS BizTalk use COM/Assemblies to extend the processing capabilities of a standard process; you can insert a COM into the message workflow to do more processing than is implemented by Microsoft. COM also allows use of Component Services providing built in object pooling, security, and control interface.
Wikipedia has a good definition of GUID. Note that Microsoft has a formatting that is not necessarly used in the rest of development community.
COM by itself does not resolve DLL version issues. It enables you to extend software incrementally if you use the COM versioning capability. So if you have an application that uses a COM to convert XML to Text (for example) and you want to enhance, you can create a new version (2.0) which you can roll-out slowly as you update the source application to use the new COM. This way you could (if need be) have a switch statement that can still use the old COM if required by system limitations, or use the new one (they would be different DLLs).
COM is a lot of different things. I recommend Don Box's book, Essential COM as a good way to learn.
At a bare minimum, a COM object is an object that exposes a single interface, IUnknown. This interface has 3 methods, AddRef, Release, and QueryInterface. AddRef/Release enables the object to be reference counted, and automatically deleted when the last reference is released. QueryInterface allows you to interrogate the object for other interfaces it supports.
Most COM objects are discoverable. They are registered in the registry under HKEY_CLASSES_ROOT with an identifying GUID, called a CLSID (class ID). This enables you to call CoCreateInstance to create an instance of a registered object if you know a GUID. You can also query the registry via a COM API for the CLSID that backs a ProgId (program id), which is a string that identifies the object.
Many COM objects have typelibs that specify the interfaces and methods the object supports, as well as IDispatch which has a method, Invoke, that allows you to dynamically call methods on the object. This enables the object to be used from scripting languages that don't support strong typing.
Some objects support being run in a different process, on a different thread, or on a different machine. COM supports marshalling for these types of objects. If possible, a standard marshaller can use the object's typelib to marshal calls to the object, but custom marshallers can be provided as well.
And there's a whole lot more to COM objects, I'm barely scratching the surface.
10,000 foot view:
COM is the communication mechanism for software components. Example, you can interact with COM interfaces (COM interop in .NET) to use functionality not exposed through a common interface (.NET assembly).
GUIDs are explained fairly decent on Wikipedia http://en.wikipedia.org/wiki/Globally_Unique_Identifier
I always understood LIB files to be object files for the C++ linker. They contain the code for all objects in a cpp file. The compiler optimizes when it links disregarding portions of the object file that it doesn't need.
Someone please clarify as I am sure I butchered some of this.
COM is Microsoft's Component Object Model, a binary-compatible interface for programs written in various languages to interoperate with each other. It is the "evolutionary step" between the OLE and .NET technologies.
If you want to learn about COM from the C++ perspective, take a look at Don Box's Essential COM, or ATL Internals by Rector and Sells.
The group microsoft.public.vc.atl is probably the best place to ask questions you can't get answers for here. It's primarily an ATL newsgroup, but it seems to be the newsgroup with the most traffic for general COM questions as well. (just be prepared for the usual newsgroup curtness & impatience)
COM is a method to develop software components, small binary exe, that provides services for applications, OS and other components. Developing custom COM comnponent is like developing Object oriented API. GUID is a Global unique ID and used to identify a COM component uniquely.
You can refer a very good book by Dale Rogerson for more details. Inside COM
I've been using a 32 bit COM library by registering it with regsvr32 and all works fine. Since I need to access it from a 64 bit process, I'm now registering it as COM+ through the Component Services administrative tool. Problem is, it seems that not all of the COM interfaces are exposed anymore. What could be the reasons for this?
There're two aspects of this problem.
First, you manually control which classes are exposed through COM+ by adding these classes only into the COM+ application. The classes you don't include will be instantiated in-proc and this instantiation will just fail because of 32-bit/64-bit incompatibility.
Then comes marshaling. In order to give the consumer an interface pointer of the newly created object COM+ needs to know how to marshal that interface. Unless you implement marshalling on your own default marshalling is used. Default marshalling will work only if the following requirements are met: the COM server contains a type library, the interface is included into that type library and the interface is fully Automation-compatible. The latter roughly means that none of that interface's methods have parameters of custom types like structs for example (interfaces are okay). If these requirements are not met COM+ will return E_NOINTERFACE when the consumer invokes CoCreateInstance() or IUnknown::QueryInterface(). See this similar question: What is required to enable marshaling for a COM interface? You basically have three choices: not query the violating interface, implement custom marshalling (which I don't currently know where to start with) or introduce a new intermediate interface which would be Automation-compatible.