COM: Creating a COM Component using C++ (Part-5)

As of now we have created our COM component. Now it is the time to test our component. In this article we are going to create a C++ client application to test our component.

Usually we need to follow the below steps while creating a component test application.

  • Initialize COM library
  • Create an instance of our component
  • Invoke the component methods
  • Uninitialize COM library

Lets create our test application based on above steps.

Initialize COM library – To initialize the COM library we should use CoInitializeEx function. The syntax of this function is:

HRESULT CoInitializeEx(_In_opt_ LPVOID pvReserved, _In_ DWORD dwCoInit);

Here pvReserved is the optional parameter and it must be NULL. dwCoInit is used to determine the concurrency model and initialization options for the thread. Following are the valid values:

  • COINIT_APARTMENTTHREADED
  • COINIT_MULTITHREADED
  • COINIT_DISABLE_OLE1DDE
  • COINIT_SPEED_OVER_MEMORY

Use Apartment threading model for serialization and multi-threaded model for non-serialization calls to the objects.

In our test application we use COINIT_APARTMENTTHREADED value.

Create an instance of our component – Once the COM library is loaded; it is the time to create an instance of our component. CoCreateInstance is the COM function which will creates a single object of the class. This function takes CLSID as an argument and creates an object of the class which is associated with CLSID. The syntax of this function is:

HRESULT CoCreateInstance(
  _In_   REFCLSID rclsid,
  _In_   LPUNKNOWN pUnkOuter,
  _In_   DWORD dwClsContext,
  _In_   REFIID riid,
  _Out_  LPVOID *ppv
);

Here rclsid is the CLSID of the associated class. In our case it should be the CLSID of HelloComponent. pUnkOuter is pointer to aggregate object. We are not using any aggregation in our component; so, in our case it should be NULL. dwClasContext is the context in which the newly created object will run. We will use CLSCTX_INPROC_SERVER value; to instruct to run the it in the same process. riid is the interface ID. In our case it is IID_IHello. *ppv is the value the function returns. In our case, it should return an instance to CHelloComponent class.

Invoke the component methods -Once we have an instance to the component; we can call component methods through instance. Once it is done; we need to release the object reference; So, the component can be freed from the memory.

Uninitialize COM library – By calling CoUninitialize function; we can release the COM library from memory.

Lets combine all together; below is the code.

// TestApp.h
//
#include "HelloComponent.h"
#include "Hello.h"

#include <comutil.h>
#include <comdef.h>
#include <iostream>

Save the above code into “TestApp.h” file. And save the below implementation file into “TestApp.cpp”.

// TestApp.cpp
//
#include "TestApp.h"

using namespace std;

void main()
{
	// Initialize COM Library
	// 
	HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
	if ( FAILED(hr) )
	{
		cout << _com_error(hr).ErrorMessage() << endl;
 		exit(0);
 	}

 	// Create instance
 	// 
 	CHelloComponent *pHello = NULL;
 	hr = CoCreateInstance(CLSID_HelloComponent, NULL, CLSCTX_INPROC_SERVER, IID_IHello, (LPVOID *)&pHello); 	
 	if ( SUCCEEDED(hr) )
 	{
 		if ( pHello != NULL )
 		{
 			pHello->SayHello(L"CodeSteps");
			pHello->Release();
		}
	}
	else
	{
		cout << _com_error(hr).ErrorMessage() << endl;
	}

	// Uninitialize COM Library
	// 
	CoUninitialize();
}

Now lets compile the client application.

cl /EHsc TestApp.cpp

This will compile and generate “TestApp.exe”. Once we run the application; it should display “Hello, CodeSteps” message.

Lets run the application. Once we run it; It is displaying “Class not registered” error message. It seems our client application is not working as we expected.

We will review our component and test application in our next article.

**

1 comment for “COM: Creating a COM Component using C++ (Part-5)

Leave a Reply