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, ®ID); 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
- COM初探(四)——本地EXE COM服务器
- COM初探(四)——本地EXE COM服务器
- 本地EXE COM服务器
- COM---EXE中的服务器
- COM学习(四)——COM中的数据类型
- COM初探(一)
- COM初探(二)
- COM初探(三)
- 连接COM与.NET的桥梁(三)——COM服务器的COM Interop方式
- COM初探(五)——从IDispatch接口继承
- COM初探(五)——从IDispatch接口继承
- COM初探
- COM初探
- 《COM技术内幕》读书笔记——第10章 EXE中的服务器 代码调试
- Inside COM读书笔记-----ExE中的服务器
- COM技术初探(一)
- COM技术初探(二)
- COM技术初探(一)
- CentOS 6.4 编译安装 gcc-4.8.0
- 关于安卓实训(打飞机游戏)的心得体会
- Pop上手体验(i-v)
- Android初学点滴积累(操作篇)
- Ubuntu下面安装eclipse for c++
- COM初探(四)——本地EXE COM服务器
- 【解惑】杨中科说给弟弟的话
- 安装配置MongoDB
- [LeetCode]—Valid Palindrome 回文判断
- 模糊测试 学习
- ATL/COM----IDL和MIDL之详解 .
- IOS中的UIScrollView简单应用(转)
- Ftp客户端程序
- 使用JWplayer出现Video not found or access denied的问题