gerry99
asked on
Console program as COM server
I've got an existing console program that we'd like to add
a COM interface to. We'd like it to be a COM server for
a particular interface, that will query it for some data.
Using VC++ 5.0 and the ATL Wizard I've produced a COM server that is a Windows program without the UI. My question is: Do I need to have a HINSTANCE pointer to be
a COM server? Microsoft is using a macro generated table to
provide access to my COM interface. Is this necessary?
Does anyone have the skeleton code for a COM server that is
a console application?
Wizard generated code:
CExeModule _Module;
BEGIN_OBJECT_MAP(ObjectMap )
OBJECT_ENTRY(CLSID_quotag, Cquotag)
END_OBJECT_MAP()
////////////////////////// ////////// ////////// ////////// ////////// ////////// /
//
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
{
lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
HRESULT hRes = CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call
// instead to make the EXE free threaded.
// This means that calls come in on a random RPC thread
// HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
_ASSERTE(SUCCEEDED(hRes));
_Module.Init(ObjectMap, hInstance);
_Module.dwThreadID = GetCurrentThreadId();
TCHAR szTokens[] = _T("-/");
int nRet = 0;
BOOL bRun = TRUE;
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL)
{
if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
{
_Module.UpdateRegistryFrom Resource(I DR_Com, FALSE);
nRet = _Module.UnregisterServer() ;
bRun = FALSE;
break;
}
if (lstrcmpi(lpszToken, _T("RegServer"))==0)
{
_Module.UpdateRegistryFrom Resource(I DR_Com, TRUE);
nRet = _Module.RegisterServer(TRU E);
bRun = FALSE;
break;
}
lpszToken = FindOneOf(lpszToken, szTokens);
}
if (bRun)
{
hRes = _Module.RegisterClassObjec ts(CLSCTX_ LOCAL_SERV ER,
REGCLS_MULTIPLEUSE);
_ASSERTE(SUCCEEDED(hRes));
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
_Module.RevokeClassObjects ();
}
CoUninitialize();
return nRet;
}
a COM interface to. We'd like it to be a COM server for
a particular interface, that will query it for some data.
Using VC++ 5.0 and the ATL Wizard I've produced a COM server that is a Windows program without the UI. My question is: Do I need to have a HINSTANCE pointer to be
a COM server? Microsoft is using a macro generated table to
provide access to my COM interface. Is this necessary?
Does anyone have the skeleton code for a COM server that is
a console application?
Wizard generated code:
CExeModule _Module;
BEGIN_OBJECT_MAP(ObjectMap
OBJECT_ENTRY(CLSID_quotag,
END_OBJECT_MAP()
//////////////////////////
//
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
{
lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT
HRESULT hRes = CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call
// instead to make the EXE free threaded.
// This means that calls come in on a random RPC thread
// HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
_ASSERTE(SUCCEEDED(hRes));
_Module.Init(ObjectMap, hInstance);
_Module.dwThreadID = GetCurrentThreadId();
TCHAR szTokens[] = _T("-/");
int nRet = 0;
BOOL bRun = TRUE;
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
while (lpszToken != NULL)
{
if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
{
_Module.UpdateRegistryFrom
nRet = _Module.UnregisterServer()
bRun = FALSE;
break;
}
if (lstrcmpi(lpszToken, _T("RegServer"))==0)
{
_Module.UpdateRegistryFrom
nRet = _Module.RegisterServer(TRU
bRun = FALSE;
break;
}
lpszToken = FindOneOf(lpszToken, szTokens);
}
if (bRun)
{
hRes = _Module.RegisterClassObjec
REGCLS_MULTIPLEUSE);
_ASSERTE(SUCCEEDED(hRes));
MSG msg;
while (GetMessage(&msg, 0, 0, 0))
DispatchMessage(&msg);
_Module.RevokeClassObjects
}
CoUninitialize();
return nRet;
}
No way gerry..
EXE-servers need a message loop. period
Your safest bet:
Port your code to an ATL-exe COM server. If your console
application is "clean", that should give you not too
much trouble.
Good Luck
EXE-servers need a message loop. period
Your safest bet:
Port your code to an ATL-exe COM server. If your console
application is "clean", that should give you not too
much trouble.
Good Luck
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
altena,
Your answer makes sense. However, why do EXE COM servers need a message loop? COM is a binary object method interface that does not seem to mention windows messages anywhere. I think of it as a way to call the functions of a module, why would I need a message loop?
The program I am working with is a high volume information server that reads new messages from an input file and diseminates them to clients who have made socket connections on the internet. Providing the COM interface will allow this program to add support for a query we normally make to our database. However, COM support is not meant to be the primary function of this server. If I add a message loop, can I run it from one of our threads, instead of the main?
Your answer makes sense. However, why do EXE COM servers need a message loop? COM is a binary object method interface that does not seem to mention windows messages anywhere. I think of it as a way to call the functions of a module, why would I need a message loop?
The program I am working with is a high volume information server that reads new messages from an input file and diseminates them to clients who have made socket connections on the internet. Providing the COM interface will allow this program to add support for a query we normally make to our database. However, COM support is not meant to be the primary function of this server. If I add a message loop, can I run it from one of our threads, instead of the main?
Good Questions gerry...
I will answer the first one:
"Why do EXE COM servers need a message loop?"
Com needs a way to call your "binary object method interface" and
to do that it will send messages to a hidden window that com
creates whenever your exe-com server gets started.
Now if you do not have a message loop, com can send all the messages it wants, they will not get processed....
I hope that makes the pieces fall in place.
I will answer the first one:
"Why do EXE COM servers need a message loop?"
Com needs a way to call your "binary object method interface" and
to do that it will send messages to a hidden window that com
creates whenever your exe-com server gets started.
Now if you do not have a message loop, com can send all the messages it wants, they will not get processed....
I hope that makes the pieces fall in place.
Also, a console app has the _CONSOLE macro defined instead of _WINDOWS. Dunno whether it makes a difference or not with ATL.