进程外COM内存释放不及时、权限问题导致实例化进程外COM接口失败

参考资料:
https://bbs.csdn.net/topics/391821709?page=1
http://benworld.iteye.com/blog/1988445
https://www.cnblogs.com/baiyanhuang/archive/2009/11/22/1730724.html
在上一篇《32位com调用64位进程外com的例子》中提到进程外COM组件的两种实例化方式
一、 进程外COM内存释放不及时的原因
方法一:创建唯一实例(调用结束后,进程立刻退出)
HRESULT hr = S_FALSE;
hr = hr = CoCreateInstance(
CLSID_TopologyPretreatment,
NULL,
CLSCTX_LOCAL_SERVER,
IID_ITopologyPretreatment,
(void**)&m_pTopPre);

方法二:创建多个实例(调用结束后,进程约30分钟后才退出)
HRESULT hr = S_FALSE;
IClassFactory* pFactory;
hr = CoGetClassObject(CLSID_TopologyPretreatment, CLSCTX_LOCAL_SERVER, NULL, IID_IClassFactory, (LPVOID*)&pFactory);
hr = pFactory->CreateInstance(NULL, IID_ITopologyPretreatment, (void**)&m_pTopPre);

分析为什么采用方法二实例化之后,调用结束,进程没有立刻退出呢?
还未找到原因,后面补充!

二、权限问题导致实例化进程外COM接口失败
首先分析了CoCreateInstance的实现原理,发现与此并无关系。
然后纠结是否是进程外COM导致,发现也说不通。
最后发现出在了exe本身权限上面,原因是在创建进程外COM时,设置了UAC执行权限为【requireAdministrator (/level=‘requireAdministrator’)】导致。将此处的执行权限修改为【asInvoker (/level=‘asInvoker’)】即可。
在这里插入图片描述

三、过程中分析总结
1、CoCreateInstance的内部实现原理
在这里插入图片描述
CoCreateInstance(…)
 {
 //…
 IClassFactory *pClassFactory=NULL;
 CoGetClassObject(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, (void )&pClassFactory);
 pClassFactory->CreateInstance(NULL, IID_IUnknown, (void
)&pUnk);
 pClassFactory->Release();
 //…
}

2、CoCreateInstance的使用
IUnknown pUnk=NULL;
IObject pObject=NULL;
CoInitialize(NULL);
CoCreateInstance(CLSID_Object, CLSCTX_INPROC_SERVER, NULL, IID_IUnknown, (void
)&pUnk);
pUnk->QueryInterface(IID_IOjbect, (void**)&pObject);
pUnk->Release();
pObject->Func();
pObject->Release();
CoUninitialize();

3、注册表在COM中的重要作用
首先要知道GUID的概念,COM中所有的类、接口、类型库都用GUID来唯一标识,GUID是一个128位的字串,根据特制算法生成的GUID可以保证是全世界唯一的。 COM组件的创建,查询接口都是通过注册表进行的。有了注册表,应用程序就不需要知道组件的DLL文件名、位置,只需要根据CLSID查就可以了。当版本升级的时侯,只要改一下注册表信息就可以神不知鬼不觉的转到新版本的DLL。

4、UAC执行级别
asInvoker (/level=‘asInvoker’) :默认执行级别asInvoker
highestAvailable (/level=‘highestAvailable’) :users组的环境下,执行可执行程序,requireAdministrator会要求输入管理员账号的密码,highestAvailable则会获取当前用户最高权限
requireAdministrator (/level=‘requireAdministrator’):users组的环境下,执行可执行程序,requireAdministrator会要求输入管理员账号的密码,highestAvailable则会获取当前用户最高权限

5、通过工具查询
方法一:任务管理器中,选择列,勾上“特权”一项,在详细信息中就可以看到了
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39116201/article/details/83895888