How do you create a COM DLL in Visual Studio 2008? - c++

It's been ages since I've written a COM dll. I've made a couple of classes now, that inherit from some COM interfaces, but I want to test it out. I know I have to put a GUID somewhere and then register it with regsvr32, but what are the steps involved?
Edit: Sorry, forgot to mention I'm using C++.

To create a new ATL COM project you can proceed as follow:
File/New Project
Visual C++/ATL/ATL Project
Customize it settings, and press finish when done
You have created a new dll, but it is empty, to add a COM object you can do this:
Project/Add Class
Visual C++/ATL/ATL simple object, press add
Give the name you want (like MyObject), and press finish to add it
If you want that an object implement an interface
In the class view select the object class (CMyObject)
Right click/Add/Implement Interface...
You can select which Interface will implement
From an .idl file already in your projects files
From a .tlb/.dll/.exe which have a type library embedded
From an object already registered
When done press finish
PS: It is much easier to create a new ATL project with the same name in a different folder, and add the files you have customized. The wizard does several tasks and create several customized files.
For larger projects that are difficult to add file by file, I do the same but instead of adding my files to the new project I start copying the settings from the new projects to the old one, and adding any additional file that the wizard has created and fixing headers like stdafx.h to merge the new settings.
PPS: If you want that your dll to support MFC, instead of selecting ATL Project you have to select MFC/MFC Dll. When you add the ATL Simple Object the wizard will ask to add ATL support to the project.

You need to write a function called DllGetClassObject and export it. That function is responsible for allocating a "class factory", which you also have to write, and which is in turn capable of allocating instances of your COM object. It has to implement IClassFactory.
It's not too hard to do. The alternative is to use ATL (see xhantt's answer) which in theory does this for you, but in practice it's a real mess. Somehow it manages to encapsulate the complexity of COM inside an abstraction layer that is even more complicated. Good luck trying to move an object between DLLs for example.
But you could run the ATL wizard just to see an example of how to declare DllGetClassObject. Implementing IClassFactory is very easy - just one method that news-up an object.
Then you need to register your DLL - i.e. put keys into the registry. The regsvr32 tool cannot do this without further help from you. You have to write and export another function called DllRegisterServer, which does all the hard work. All that regsvr32 does is load the DLL, look up DllRegisterServer and call it.
Again, ATL has a way of implementing this for you, but it does it by reading a kind of script full of registry modification instructions, stored in an .rgs file that gets embedded into your DLL's resources. If you accidentally put any kind of syntax error into this file, the registration fails silently.
So again, you may actually find it simpler to write a few lines of code to tweak the registry yourself. Here are the details.
If you used C# instead, you wouldn't have any of these problems. Everything is encapsulated very cleanly. It actually works much better than C++ as a tool for developing COM objects.

When you build the solution, it automatically registers the dll.
And also it creates two files _i.c and .h file.
To test the dll create the sample application:
Create sample Win32 application. Include the _i.c and .h in the cpp file of the win32 application which has main function
Call CoInitialize();
Declare a interface pointer
CComPtr pMyInterface = NULL; // where IMyInterface is declared in _i.c
Create the instance
pMyInterface.CoCreateInstance(CLSID_MyClass); // CLSID_MyClass is GUID representing the
CoClass
Call the APIs present in the Interface
Call CoUnInitialize();

Related

Use _COM_SMARTPTR CreateInstance without Registration within the same DLL

I'm currentyl trying to write a DLL which consumes a Typelib (.tlb) registered in the system. This Typelib requires that I implement two interfaces with my own classes, and register one of them within the Running Object Table, which I did in an ATL project using Visual Studio 2015.
The Application that consumes my DLL should have no knowledge of COM at all, everything should work there behind the scenes and hidden by the DLL I'm implementing.
Within my DLL, at some point I'm trying to get Instances of a clas MyClass which implements the above mentionend COM-Interfaces of the Typelib. The code looks like this:
IInterfaceClassPtr dataPtr;
hr = dataPtr.CreateInstance(CLSID_MyClass);
IInterfaceClassPtr is actually a Macro (all of this is generated by Visual Studio), which looks like this:
_COM_SMARTPTR_TYPEDEF(IExampleInterface, __uuidof(IExampleInterface));
IExampleInterface is defined in the Typelib I consume, and implemented by MyClass.
If I'm registering my own DLL using regsvr32, everything works fine. But I want to avoid that because it requires Admin privileges.
If my DLL is not registered, the above call fails with HRESULT "0x80040154, Class is not registered". I read the article Registration free activation of COM-Components (And a few others). But I can't tweak the consuming applications' manifest here - the class (MyClass) I'm trying to activate lives in the very same DLL as the mentioned "CreateInstance" call.
What do I need to do to be able to Create Instances of these Classes without using regsvr32 or some Manifest-Tweaking?
You can create concrete instances of your objects directly within your DLL (assuming the classes are implemented there).
CComObject<CMyClass>* pMyClassPtr;
CComObject<CMyClass>::CreateInstance(&pMyClassPtr);
pMyClassPtr->AddRef();
CComObject<T>::CreateInstance creates an instance of a COM object by directly calling new CComObject<T> so it bypasses the registry.
You can then use QueryInterface on the object to get your required interface.
IInterfaceClassPtr spIInterface;
pMyClassPtr->QueryInterface(&spIInterface);

Beginners qestion: How to import / access a .NET assembly from a Visual Studio 2008 C++ ATL project?

I'm just taking my first steps in the Visual Studio 2008 / C++ world, and I do so by trying to create a new CTI Connector for Salesforce. I managed the first part without too much hassle, so now I have an almost-functional CTI Connector. There's only one, but vital part missing: The actual connection to the Call Center system.
The manufacturer provides a .NET integration DLL that also provides a COM interface. I've successfully used the COM part before in Delphi (my native environment...) and I wouldn't mind to use the COM approach here as well, though using the .NET interface seems a bit more natural to me.
Now I do have an ATL project created in Visual Studio 2008 SP1, providing a COM interface to the Salesforce side of the connection.
I do also have a .NET dll providing the interface to the Call Center, and a registered COM object that does the same.
What I don't have is the slightest idea how to get this into my C++ project.
From my Delphi experience I was expecting Visual Studio to have some Import feature that automagically builds a class around the integration object in order for me to simply use it, but obviously there isn't, at least not for ATL projects. Changing the project type to something else is currently not an option, as this is the documented way to interface Salesforce.
I found some hints to simply include the .tlb in a .cpp file in order to use the COM object, and doing so does indeed help IntelliSense to recognize the Namespace and Classes of this object, but this is where I'm stuck.
So my qustions are:
Am I required to create the methods and events provided by the .NET dll / COM object manually, or is there a simpler way to get them automatically?
If manual creation is required, how do I access the Event interface of the integration object?
How do instantiate the integration object, and do I have to do so at all?
Until now, I've created a class called CAgentIntegration. In the .cpp file I import the typelib provided with the DLL (AgentIntegration.dll and AgentIntegration.tlb), both files are present in the source folder of my project.
In the constructor of CAgentIntegration, I try to somehow access the imported object. IntelliSense obviously recognizes the Namespace AgentIntegration, because it offers the AgentClient class as code completion. It is the part after AgentClient of which I have no idea. The example below clearly doesn't work because the compiler complains that to the left of -> a class or struct is required.
#include "StdAfx.h"
#import "AgentIntegration.tlb"
CAgentIntegration::CAgentIntegration(void)
{
AgentIntegration::AgentClient->Initialize();
}
CAgentIntegration::~CAgentIntegration(void)
{
}
The following image is from Object Browser in Visual Studio, after adding the .tlb to it. Maybe this helps to better understand how things are arranged inside the DLL.
Please bear in mind that this is a qustion from someone who doesn't even know the correct syntax to include the integration object into the project, so the answer may be way less complex than you may assume - it would probably be enough to just provide a short code sample that I can use as a template to start from. On the other hand, "just use #import" as an answer would not help me much because I don't know how to use it ;-)
Thanks in advance
Patrick

How would I go about invoking the ui from within a DLL?

This may be too broad a question, but I have a DLL that contains a UI. It is currently invoked by an EXE. What steps would I do to try and invoke the UI within the DLL? Or put another way, how would I go about teasing out the code that would invoke the UI as it happens in the EXE?
Looks like you have access to source for both dll and executable that uses it. so what you are doing is writing a host for that dll from scratch.
Create a MFC application from VS project templates (make it the same kind as main executable, dialog, single document, multiple document, etc).
Look at what function dll exports, also look at its headers and best of all -- documentation.
Search source code of main exe and find the places the dll functions are called.
Figure out what is being done and why.
Narrow down scenarios you want to reproduce (initialize dll, show basic UI and tear down)
Start reproducing that code in your example app.
Copy the dll call, see what parameters it takes, see how those are initialized, etc.
Fix errors as they come up.

Can I access in ActiveX project functions from another ATL simple object in the same project?

I have an ActiveX control project (.ocx) which contains one main control class and several other ATL simple objects. The main control class exposes many functions; it would be practical if I could use some of these functions in the other ATL objects. Is this possible? Do I have to instantiate my ActiveX control within one of its exported ATL objects (and how?), or is there another way?
Although you did not mention it in your question I am assuming you do not currently have access to the interface/coclass decalration of the object you want to create.
If the control you want to use has an application ID associated with it you can use the #import directive to pull in the interface and type definitions directly into your C++ source file. For example if the application ID is "Library.MainObject" you could do something like below
#import "progid:Library.MainObject"
This will access the objects type library directly. If it doesn't have an application ID associated with it there are a few extra steps that you may have to take. One way to acquire the type library is to use the OLE Object Viewer utility that ships with Visual Studio. Once you find it in the Object Viewer you can save the type library as a file. If you can't find it in the Object Viewer you can try opening the OCX module directly and if it contains a type library you can export it to a file. Once you have the type library you can use #import to pull in the declarations.
#import "typelibraryname.tlb"
Once you have access to the declarations you can call CoCreateInstance just like you would for any other COM object. You can use __uuidof(typename) to get the GUID of an interface or co-class.

Convert Win32 Application to Object

I'm pretty new to WinAPI programming, and have written a Win32 application for screen capture. When I run the program, the cursor immediately changes to a crosshair and I can click and drag to capture a portion of the screen and save it to file.
However, I'd now like to modify my program so that it doesn't contain a main method (WinMain) and essentially turn it into an object class rather than an application class so I can call functions from other programs. I haven't been able to find a good resource on how to do this, as I believe WinMain carries out special functionality under the hood so I can't simply change the name of the method.
Can anyone suggest some good resources or tutorials that address this?
There are many ways to do that, but you have fist move one step back:
How do yopu expect your "program" (let us continue to call that way) to be called?
With which parameters and what return type?
Then, what kind of API do you want to expose? A C++ class in header? a C++ class from a static library?
A C function exported from a DLL? an COM object?
There are many sample on how a library or a DLL or a COM library looks like (just try google those keywords).
The simple way is most likely to set up a library or a DLL project (most IDE have wizard that provide empty skeletons), than paste in it the relevant code that you require to leave there, letting it be called from the exposed function or class method.
A more precise answer can be given only after you decided which "form" your "object" should have.