This blog is only to remind myself of what I've learned (from others or by myself) and only for knowledge sharing. External sources will be clearly stated in [Reference] of each article. I hope this blog won't infringe any copyrights and that it can be useful for interested blog readers.

顯示具有 COM 標籤的文章。 顯示所有文章
顯示具有 COM 標籤的文章。 顯示所有文章

2008年4月8日 星期二

COM client using COM server's interface

Goals:

(1) how to get instance of COM service

(2) how to get access of COM service APIs

(3) Usage


Sample code:

#include <iostream.h>

//!!NOTES: this part is to get CLSID and IID info

#import "..\Test_COM_service/Test_COM_service.tlb" named_guids raw_interfaces_only
using namespace TEST_COM_SERVICELib; // refer to Test_COM_service_i.c

#include <stdio.h>


void main(void)
{
// Declare and HRESULT and a pointer to
// the Simple_ATL interface
HRESULT hr;
IZTEDll *pZTEDll = NULL;

// Now we will intilize COM
hr = CoInitialize(0);

// Use the SUCCEEDED macro and see if
// we can get a pointer
// to the interface
if(SUCCEEDED(hr))
{
//NOTES: don't know why CLSCTX_INPROC_SERVER won't work

hr = CoCreateInstance(CLSID_ZTEDll, NULL, CLSCTX_ALL, IID_IZTEDll, (void**) &pZTEDll) ;

if(SUCCEEDED(hr))
{
UTC_time_info timeInfo;
timeInfo.year = 2008;
timeInfo.month = 4;
timeInfo.date = 8;
timeInfo.hour = 14;
timeInfo.minute = 0;
timeInfo.second = 0;

HRESULT res = S_OK;
res = pZTEDll->initializeKda(&timeInfo);
cout << "after initializeKda: " << res << endl;
cout << "year: " << timeInfo.year << endl;
cout << "month: " << timeInfo.month << endl;
cout << "date: " << timeInfo.date << endl;
cout << "hour: " << timeInfo.hour << endl;
cout << "minute: " << timeInfo.minute << endl;
cout << "second: " << timeInfo.second << endl;

res = pZTEDll->terminateKda();
cout << "after terminateKda: " << res << endl;

cout << "press any key to continue... " << endl;
getchar();

pZTEDll->Release();
}
else
{
cout << "CoCreateInstance Failed." << endl;
}
}
// Uninitialize COM
CoUninitialize();
}


Usage:

(1) open a "command console"
(2) Go to the directory where "Test_COM_client.exe" is located
(3) execuate Test_COM_service.exe
(4) check the result

COM-server related info

What to know:

(1) Use VC6 to create a "service-type" EXE file

(2) How to make COM server as a background service when OS boot-up

(3) How to debug COM server

---------------------------------------------------------

Use VC6 to create a "service-type" EXE file

(1) New ATL COM APP Wizard

(2) Choose Service-Type

(3) Wizard finished

(4) Add a new ATL Object

(5) Choose "Simple Object" to create an interface

(6) Fill in "Short Name" of the new simple object

(7) The result of New created Object (Interface)

(8)

(9) Add a new method "initialize" with UTC_time_info structure

(10) add a new method "un-initialize"

(11) The results of created new methods

(12) add UTC_time_info structure in IDL file

(13) Compile

How to make COM server as a background service when OS boot-up

(1) Open a "command console" window

(2) Go to the directory where "Test_COM_service.exe" is located

(3) enter command "Test_COM_service.exe -Service"

(4) enter "services" window

(5) check the availability of "Test_COM_service"

(6) manually activate it

(7) check the correctness of COM service startup

(8) check the COM service startup correctness in task bar

How to debug COM server

(1) de-activate COM service from "services" window

(2) Open a "command console" window

(3) Go to the directory where "Test_COM_service.exe" is located

(4) enter command "Test_COM_service.exe -regserver"

(5) Open COM service VC6 project

(6) press "F5" and add some breakpoints for debugging


!!NOTES:

(1) Debugging

according to testing, it seems that if "Test_COM_service.exe -regserver" is used

instead of "Test_COM_service.exe -Service", COM service will be closed

when COM client is Release its allocated COM server instance.

(2) COM startup and release

During COM server startup, the following steps will happen

(a) COM server will initialize itself

(b) COM server will enter CServiceModule::Run() and wait for messages in

the following while-loop

MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);

So any code related initialization can be placed before this while-loop.

(c) When COM server is closed automatically or manually, COM server will leave

the above while loop and leave CServiceModule::Run() subsequently.

So any code related to un-initilazation can be placed after "GetMessage" while loop.