COM初探(四)——本地EXE COM服务器

来源:互联网 发布:ubuntu打开py文件 编辑:程序博客网 时间:2024/05/31 13:15
 COM初探(四)——本地EXE COM服务器 .分类: Visual C++ 之 COM技术 2005-07-21 13:07 724人阅读 评论(0) 收藏 举报 exenullinterfaceapplication服务器serverCOM初探(四)——本地EXE COM服务器(一)目标讲述如何建立本地(Local,EXE)COM服务器的例子似乎不多,为此,本文专门讲述如何用vc手工建立本地EXE COM服务器程序。本文假设读者对COM有一定的基础。(二)准备 1)使用vc6建立Win32 Application工程,选择a simple application。 2)从stdafx.h中删除:#define WIN32_LEAN_AND_MEAN(三)建立IDL文件此文件中定义了接口ITimeBeijing和COM类TimeBeijingClassimport "oaidl.idl";[ object,  uuid(61A1C81D-82CA-44e4-A60E-7BDD8E58A833), oleautomation]interface ITimeBeijing : IUnknown//定义ITimeBeijing接口{ HRESULT GetTimeBeijing([out]int * hour, [out]int * min, [out]int * sec);};[ uuid(1E850106-D5C5-4249-86DF-40256DB3A5D2),  version(1.0)]library TimeBeijingLib{   importlib("stdole32.tlb");   [  uuid(57E9BE40-AE4F-493b-A79B-FBBF7EC7F2AE)   ]   coclass TimeBeijingClass//定义TimeBeijingClass类   {      [default] interface ITimeBeijing;   };};(四)添加COM类TimeBeijingClassTimeBeijingClass在由上面idl文件编译生成的文件中已经前置声明了。这里我们实现了它的功能(获取当前北京时间)// TimeBeijingClass.h: interface for the TimeBeijingClass class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_TIMEBEIJINGCLASS_H__E9D2F0AF_8EBB_438B_A2BC_6206DDAB91B6__INCLUDED_)#define AFX_TIMEBEIJINGCLASS_H__E9D2F0AF_8EBB_438B_A2BC_6206DDAB91B6__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include "TimeBeijing.h"class TimeBeijingClass : public ITimeBeijing  {public: TimeBeijingClass(); ~TimeBeijingClass();private: ULONG m_cRef;public: //IUnknown 方法 STDMETHOD(QueryInterface)(REFIID riid, void **ppv); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); //ITimeBeijing 方法 STDMETHOD(GetTimeBeijing)(int * hour, int* min, int * sec);};#endif // !defined(AFX_TIMEBEIJINGCLASS_H__E9D2F0AF_8EBB_438B_A2BC_6206DDAB91B6__INCLUDED_)// TimeBeijingClass.cpp: implementation of the TimeBeijingClass class.////////////////////////////////////////////////////////////////////////#include "StdAfx.h"#include "TimeBeijingClass.h"#include "time.h"#include "stdio.h"#include "TimeBeijing_i.c"//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////TimeBeijingClass::TimeBeijingClass(){ printf("TimeBeijingClass - constructor/n"); m_cRef = 0;}TimeBeijingClass::~TimeBeijingClass(){ printf("TimeBeijingClass - destructor/n");}STDMETHODIMP TimeBeijingClass::QueryInterface(REFIID riid, void **ppv){ printf("TimeBeijingClass - QueryInterface/n"); if(riid == IID_ITimeBeijing)  *ppv = static_cast<ITimeBeijing *>(this); else if(riid == IID_IUnknown)  *ppv = static_cast<ITimeBeijing *>(this); else {  *ppv = 0;  return E_NOINTERFACE; }  reinterpret_cast<IUnknown *>(*ppv)->AddRef(); return S_OK;}STDMETHODIMP_(ULONG) TimeBeijingClass::AddRef(){ printf("TimeBeijingClass - AddRef/n"); return ++m_cRef;}STDMETHODIMP_(ULONG) TimeBeijingClass::Release(){ printf("TimeBeijingClass - Release/n"); ULONG res = --m_cRef;  if(res == 0)  delete this; return res;}STDMETHODIMP TimeBeijingClass::GetTimeBeijing(int * hour, int* min, int * sec){ printf("TimeBeijingClass - GetTimeBeijing/n");  time_t ltime; struct tm *today;  time(<ime); today = localtime(<ime);  *hour = today->tm_hour; *min = today->tm_min; *sec = today->tm_sec;  return S_OK;}(五)添加工厂类TimeBeijingClassFactory类工厂可以生成类的实例。在标准的COM实现中,我们都是通过使用类工厂来得到目的接口指针的。类工厂从IClassFactory接口派生,有两个接口函数:CreateInstance和LockServer。CreateInstance用于建立目标COM类的实例并返回相应接口。LockServer用于全局的引用计数。当计数为0时,服务器自动关闭。// TimeBeijingClassFactory.h: interface for the TimeBeijingClassFactory class.////////////////////////////////////////////////////////////////////////#if !defined(AFX_TIMEBEIJINGCLASSFACTORY_H__AB2637DD_45D2_48CD_BAD8_46E372268A8C__INCLUDED_)#define AFX_TIMEBEIJINGCLASSFACTORY_H__AB2637DD_45D2_48CD_BAD8_46E372268A8C__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include <unknwn.h>class TimeBeijingClassFactory : public IClassFactory  {public: TimeBeijingClassFactory(); ~TimeBeijingClassFactory();public: //IUnknow 方法 STDMETHODIMP QueryInterface(REFIID,void**); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();  //IClassFactory 方法 STDMETHODIMP CreateInstance(IUnknown * ,REFIID ,void **); STDMETHODIMP LockServer(BOOL fLock); private: LONG m_cRef;};#endif // !defined(AFX_TIMEBEIJINGCLASSFACTORY_H__AB2637DD_45D2_48CD_BAD8_46E372268A8C__INCLUDED_)// TimeBeijingClassFactory.cpp: implementation of the TimeBeijingClassFactory class.////////////////////////////////////////////////////////////////////////#include "StdAfx.h"#include "TimeBeijingClassFactory.h"#include "stdio.h"#include "TimeBeijingClass.h"//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////extern LONG g_cObjectAndLocks;TimeBeijingClassFactory::TimeBeijingClassFactory(){ printf("TimeBeijingClassFactory - constructor/n"); m_cRef = 0;}TimeBeijingClassFactory::~TimeBeijingClassFactory(){ printf("TimeBeijingClassFactory - destructor/n");}STDMETHODIMP_(ULONG) TimeBeijingClassFactory::AddRef(void){ printf("TimeBeijingClassFactory - AddRef/n"); return InterlockedIncrement(&m_cRef);}STDMETHODIMP_(ULONG) TimeBeijingClassFactory::Release(void){ printf("TimeBeijingClassFactory - Release/n"); return ::InterlockedDecrement(&m_cRef);}STDMETHODIMP TimeBeijingClassFactory::QueryInterface(REFIID riid,void ** ppv){ printf("TimeBeijingClassFactory - QueryInterface/n"); *ppv = NULL; if(riid == IID_IUnknown || riid == IID_IClassFactory) {  *ppv = static_cast<IClassFactory *>(this);  reinterpret_cast<IUnknown*>(*ppv)->AddRef();  return S_OK; } else  return (*ppv=0),E_NOINTERFACE;}STDMETHODIMP TimeBeijingClassFactory::CreateInstance(IUnknown * pUnkOuter,REFIID riid,void ** ppv){ printf("TimeBeijingClassFactory - CreateInstance/n"); *ppv=NULL;  if(pUnkOuter != NULL)  return CLASS_E_NOAGGREGATION;  TimeBeijingClass * pTimeBeijingClass = new TimeBeijingClass; if(pTimeBeijingClass == NULL)  return E_OUTOFMEMORY;  HRESULT hr = pTimeBeijingClass->QueryInterface(riid,ppv);  if(FAILED(hr))  delete pTimeBeijingClass;  return hr; }STDMETHODIMP TimeBeijingClassFactory::LockServer(BOOL fLock){ printf("TimeBeijingClassFactory - LockServer/n"); if(fLock)  ::InterlockedIncrement(&g_cObjectAndLocks); else  {  if(0 == ::InterlockedDecrement(&g_cObjectAndLocks))   PostQuitMessage(0); } return NOERROR; }(六)服务器端主文件客户端主文件负责注册工厂类,使得外部程序可以访问本地的COM类。#include "stdafx.h"#include "TimeBeijing_i.c"#include "TimeBeijingClassFactory.h"LONG g_cObjectAndLocks;//用于全局的应用计数int APIENTRY WinMain(HINSTANCE hInstance,//程序的入口点                     HINSTANCE hPrevInstance,                     LPSTR     lpCmdLine,                     int       nCmdShow){ HRESULT hr; CoInitialize(NULL);  //初始化COM环境  //读入并注册类型库 ITypeLib* pTLib = NULL; hr = LoadTypeLibEx(L"TimeBeijing.tlb", REGKIND_REGISTER, &pTLib); pTLib->Release(); if ( FAILED(hr) ) {  MessageBox(NULL, "LoadTypeLibEx() failed", "", MB_OK);  exit(1); }  // 判断是否被SCM调用    if(strstr(lpCmdLine, "/Embedding") || strstr(lpCmdLine, "-Embedding")) {  MessageBox(NULL, "TimeBeijing Server is registering the classes",    "EXE Message!", MB_OK | MB_SETFOREGROUND);    // 工厂类  TimeBeijingClassFactory ClassFactory;    // 注册工厂类  DWORD regID = 0;  hr = CoRegisterClassObject(CLSID_TimeBeijingClass,    (IClassFactory*)&ClassFactory,   CLSCTX_LOCAL_SERVER,   REGCLS_MULTIPLEUSE,    &regID);  if ( FAILED(hr) )  {   MessageBox(NULL, "CoRegisterClassObject()", "", MB_OK);   CoUninitialize();   exit(1);  }    // 进入消息循环,直到WM_QUIT到达  MSG ms;  while(GetMessage(&ms, 0, 0, 0))  {   TranslateMessage(&ms);   DispatchMessage(&ms);  }    // 注销工厂类  CoRevokeClassObject(regID);  }  // 退出COM环境 CoUninitialize();  MessageBox(NULL, "Server is dying",   "EXE Message!", MB_OK | MB_SETFOREGROUND);  return 0;}(七)建立注册文件注册文件用于添加程序注册表信息,文件内容如下:REGEDITHKEY_CLASSES_ROOT/Justin.TimeBeijingServer.TimeBeijingClass/CLSID = {57E9BE40-AE4F-493b-A79B-FBBF7EC7F2AE}HKEY_CLASSES_ROOT/CLSID/{57E9BE40-AE4F-493b-A79B-FBBF7EC7F2AE} = Justin.TimeBeijingServer.TimeBeijingClassHKEY_CLASSES_ROOT/CLSID/{57E9BE40-AE4F-493b-A79B-FBBF7EC7F2AE}/LocalServer32 = D:/COM/Debug/COM.exe双击此文件,将注册信息加入注册表。(八)建立客户端上面的程序编译链接后就可以得到一个本地EXE COM服务器。下面为了测试,我们将建立一个客户程序。// TEST.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "TEST.h"#include "../TimeBeijing.h"#include "../TimeBeijing_i.c"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////////////////////////////////////////// The one and only application objectCWinApp theApp;using namespace std;int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){ cout << "初始化COM环境" << endl; CoInitialize(NULL); HRESULT hr; IClassFactory* pICF = NULL;//定义接口指针  ITimeBeijing *pTimeBeijing = NULL;  cout << "获取工厂接口指针" << endl; hr = CoGetClassObject(CLSID_TimeBeijingClass,   CLSCTX_LOCAL_SERVER,   NULL,  IID_IClassFactory,  (void**)&pICF); if ( FAILED(hr) ) {  MessageBox(NULL, "CoGetClassObject()", "fail", MB_OK);  exit(1); }  cout << "获取ITimeBeijing接口指针" << endl; hr = pICF->CreateInstance(NULL,  IID_ITimeBeijing,  (void**)&pTimeBeijing); if ( FAILED(hr) ) {  MessageBox(NULL, "CoCreateInstance()", "fail", MB_OK);  exit(1); }  int h, m, s; pTimeBeijing->GetTimeBeijing(&h, &m, &s);//使用接口 printf("Time NOW : %d : %d : %d/n", h, m, s);//显示结果  if ( pICF )         pICF->Release();//释放接口 if ( pTimeBeijing ) pTimeBeijing->Release();  cout << "退出COM环境" << endl; CoUninitialize(); cout << "END" << endl; getchar(); return 0;}(九)测试结果  初始化COM环境  获取工厂接口指针  获取ITimeBeijing接口指针  Time NOW : 12 : 54 : 23  退出COM环境  END


 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 泪沟和眼袋都有怎么办 脸上的汗毛很长怎么办 点痣留下褐色印怎么办 氮氧传感器坏了怎么办 考试车离合太松怎么办 胎心监护不过关怎么办 羚羊角的功效与作用发烧怎么办 小孩上课注意力不集中怎么办 2岁宝宝不会说话怎么办 小孩脖子上长淋巴结怎么办 小孩子上课注意力不集中该怎么办 脸过敏干燥起皮怎么办 脸上皮肤干燥起皮怎么办 身上皮肤干燥起皮怎么办 皮肤暗黄有色斑怎么办 我皮肤干燥暗黄怎么办 脸上有皮肤暗黄怎么办 皮肤暗黄毛孔大怎么办 脸上很干燥起皮怎么办 脸上的皮肤起皮怎么办 身体的皮肤好干怎么办 滴油雾化器炸油怎么办 已经发炎的痘痘怎么办 被养生馆骗了怎么办 做完微针结痂了怎么办 秋季脸干燥起皮怎么办 身上的皮肤太干怎么办 板材眼镜腿松了怎么办 超声刀后喝酒了怎么办 开眼角疤痕增生了怎么办 开了眼角有增生怎么办 全切双眼皮留疤怎么办 开内眼角留疤了怎么办 开眼角长了颗粒怎么办 开刀后疤痕庝痛怎么办 眼角开得太尖了怎么办 眼角开得太大了怎么办 开眼角后增生了怎么办 下颌骨宽怎么办不整容 脸两边骨头太宽怎么办 接了睫毛眼睛疼怎么办