单实例问题

rick1126 2001-12-14 10:24:32
在书上找到一个COM组件单实例的例子, 使用以后发觉一段时间以后单实例会遭到破坏, 即构造函数被使用多次, 正确地来说, 构造函数只会运行一次, 一下是相关代码, 大家看看有否问题

////////////////////////////////////////////////////////////////////////////////////////////
// 项目名称: pStream-接收端
// 文件名: Macro.H
// 文件描述: 使ActiveX自动化服务器具有单实例属性,方案是更改ActiveX的类厂对象,
// 使用和ATL编程方式相同的宏定义结构,替换自动化服务器启动时缺省的宏
// 文件版本: 1.0
// 编译器: Visual C++ 6.0
//
// 模块 pStream, Receive, TimeReceive
// Copyright (c) NetCast 2000, All rights reserved
//
// 修改历史:
// 编号 日期 人员 备注
// 1 2000.12.19 陈栋 编写宏
////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _ACTIVEX_AUTO_SERVER_SINGLE_MACRO_H
#define _ACTIVEX_AUTO_SERVER_SINGLE_MACRO_H

// 宏调用语句,非没有聚合属性的单实例
#define DECLARE_NOT_AGGREGATABLE_SINGLE(cBase, clsid, iBase, iid) public: typedef CComCreator2< CComCreatorSingle< CComObjectSingle<cBase, clsid, iBase, iid>, clsid>, CComFailCreator<CLASS_E_NOAGGREGATION> > _CreatorClass;

// 通过RegisterActiveObject注册对象,如果注册过并且引用未1
// 撤销注册动作,增加引用
// 如果引用为0,则执行动作释放对象
#define RELEASE_AND_DESTROY_SINGLE() InternalRelease(); if(dwRegister && m_dwRef == 1) { InternalAddRef(); DWORD dwtRegID = dwRegister; dwRegister = 0; ::RevokeActiveObject(dwtRegID, NULL); InternalRelease(); } if(m_dwRef == 0) { delete this; return 0; } return m_dwRef

// 定义用户类型模板,在用户类型的基础上继承用户类实现
template <class cBase, const CLSID * clsid, class iBase, const IID * iid>
class CComObjectSingle : public cBase
{
public:
// 该宏预防InternalFinalConstructRelease()调用时出现断言
DECLARE_PROTECT_FINAL_CONSTRUCT();

ULONG dwRegister;
typedef cBase _BaseClass;
CComObjectSingle(void* = NULL)
{
// 引用
this->InternalAddRef();

_Module.Lock();

dwRegister = NULL;

// 初始化IUnknown接口
LPUNKNOWN pIUnknown = NULL;

// 查找已运行实例
::GetActiveObject(*clsid, NULL, &pIUnknown);

// 如果未找到,运行实例
if(!pIUnknown){
if(_InternalQueryInterface(IID_IUnknown, (void **) &pIUnknown) == S_OK){
// 注册对象clsid并使其它应用可找到已运行的实例
::RegisterActiveObject(pIUnknown, *clsid, ACTIVEOBJECT_STRONG, &dwRegister);
pIUnknown->Release();
}
pIUnknown = NULL;
}
else{
pIUnknown->Release();
}

this->InternalRelease();
}
virtual ~CComObjectSingle()
{
// 置引用值
m_dwRef = 1L;
FinalRelease();
_Module.Unlock();
}
// 引用
STDMETHOD_(ULONG, AddRef)()
{
return InternalAddRef();
}
// 释放
STDMETHOD_(ULONG, Release)()
{
RELEASE_AND_DESTROY_SINGLE();
}
// 查询接口
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
{return _InternalQueryInterface(iid, ppvObject);}
// 创建com对象实例
static HRESULT WINAPI CreateInstance(CComObjectSingle<cBase, clsid, iBase, iid>** pp);
};

// 创建对象
template <class cBase, const CLSID * clsid, class iBase, const IID * iid>
HRESULT WINAPI CComObjectSingle<cBase, clsid, iBase, iid>::CreateInstance(CComObjectSingle<cBase, clsid, iBase, iid>** pp)
{
_ASSERTE(pp != NULL);
HRESULT hRes = E_OUTOFMEMORY;

// 初始化一IUnknown 引用
LPUNKNOWN pIUnknown = NULL;

// 查找已运行的对象
::GetActiveObject(*clsid, NULL, &pIUnknown);

// 如果未找到,运行实例
if(!pIUnknown){
CComObjectSingle<cBase, clsid, iBase, iid>* p = NULL;
ATLTRY((p = new CComObjectSingle<cBase, clsid, iBase, iid>()));
if (p != NULL){
p->SetVoid(NULL);
p->InternalFinalConstructAddRef();
hRes = p->FinalConstruct();
p->InternalAddRef();
p->InternalFinalConstructRelease();
if (hRes != S_OK){
delete p;
p = NULL;
}
else{
do_nothing;
}
}
*pp = p;
}
else{
// 否则符合已运行实例指针
iBase * piBase = NULL;
pIUnknown->QueryInterface(*iid, (LPVOID*) &piBase);
*pp = (CComObjectSingle<cBase, clsid, iBase, iid>*) piBase;
pIUnknown->Release();
}

return hRes;
}

template <class T1, const CLSID* clsid>
class CComCreatorSingle
{
public:
static HRESULT PASCAL CreateInstance(void* pv, REFIID riid, LPVOID* ppv)
{
_ASSERTE(*ppv == NULL);
HRESULT hRes = E_OUTOFMEMORY;

LPUNKNOWN pIUnknown = NULL;

::GetActiveObject(*clsid, NULL, &pIUnknown);

if(!pIUnknown)
{
T1* p = NULL;
ATLTRY(p = new T1(pv))
if (p != NULL)
{
p->SetVoid(pv);
p->InternalFinalConstructAddRef();
hRes = p->FinalConstruct();
p->InternalFinalConstructRelease();
if (hRes == S_OK)
hRes = p->QueryInterface(riid, ppv);
if (hRes != S_OK)
delete p;
}
}
else
{
hRes = pIUnknown->QueryInterface(riid, ppv);

pIUnknown->Release();
}
return hRes;
}
};

#endif // _ACTIVEX_AUTO_SERVER_SINGLE_MACRO_H
...全文
138 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
三杯倒 2001-12-14
  • 打赏
  • 举报
回复
1111

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧