使用Excel COM组件导出数据后释放 Excel进程不能正常结束

简介: 分析一下自己的错误: 首先用Range的GetItem取到的是一个VARIANT,内含IDispatch接口,我一直以为内含的是一个BSTR,所以我已一开始直接用 _bstr_t   bs(rg.GetItem(_variant_t((short)1),_variant_t((short)2))); 来获取字符串(主要是的确能获得字符串),根据lop5712(LOP)的提醒,发现返回的VARIANT是接口并不是BSTR; 看来_bstr_t这个类可以把IDispatch接口直接转换为字符串。

分析一下自己的错误:

首先用Range的GetItem取到的是一个VARIANT,内含IDispatch接口,我一直以为内含的是一个BSTR,所以我已一开始直接用
_bstr_t   bs(rg.GetItem(_variant_t((short)1),_variant_t((short)2)));
来获取字符串(主要是的确能获得字符串),根据lop5712(LOP)的提醒,发现返回的VARIANT是接口并不是BSTR;

看来_bstr_t这个类可以把IDispatch接口直接转换为字符串。

跟踪代码发现,在给一个_bstr_t或COleVariant赋值VARIANT类型的时候,如果VARIANT不是VT_BSTR,这时候_bstr_t会调用OLE函数VariantChangeType进行类型转换,根据MSDN说明,如果转换是从一个IDispatch到BSTR,这时VariantChangeType会尝试接口的Value属性,而rg.GetItem返回的接口的确存在Value属性,因而_bstr_t和COleVariant能取到值。

根据上述原因,我们应该释放VARIANT所含的接口,但我用#import   指令导入Excel库的时候,却没有碰到这个问题,看来两种方式的代码是有区别的。

首先谈一下#import导入的情况:

Range   的GetItem声明为:
inline   _variant_t   Excel::Range::GetItem   (   const   _variant_t   &   RowIndex,   const   _variant_t   &   ColumnIndex   )   {
        VARIANT   _result;
        _com_dispatch_method(this,   0xaa,   DISPATCH_PROPERTYGET,   VT_VARIANT,   (void*)&_result,  
                L "/x000c/x080c ",   &RowIndex,   &ColumnIndex);
        return   _variant_t(_result,   false);
}

这种情况下返回的是_variant_t(_result,   false);
也就是说已经对返回的VARIANT用_variant_t包装了,而且重要的是第二个参数,第二个参数false告诉_variant_t包装VARIANT时仅仅把内容完整的复制过来,如果不含这个false(默认为true),_variant_t将采用OLE函数VariantCopy,根据MSDN,VariantCopy在碰到BSTR时会再分配一个空间,碰到接口类型时将对接口添加一个引用,所以_variant_t(_result,   false)直接把返回值存起来,并在析构的时候自动释放内含的IDispatch。

再来看一下用MFC导入的情况:
声明如下:
VARIANT   Range::GetItem(const   VARIANT&   RowIndex,   const   VARIANT&   ColumnIndex)
这时候返回的是未经过包装的VARIANT,不会自动释放,需要手动完成。

如果用_bstr_t   bs(rg.GetItem(_variant_t((short)1),_variant_t((short)2)));
将丢失返回的VARIANT,这就是我发生的错误。
我看到有的网站上的例子是这样的:
_variant_t   vt(rg.GetItem(_variant_t((short)1),_variant_t((short)2)));

_variant_t   vt=rg.GetItem(_variant_t((short)1),_variant_t((short)2));
这样做其实也是有问题的,虽然取到了VARIANT的值,但是不带false的_variant_t会添加一个引用,析构_variant_t只会Release一次,仍然造成对象释放不完全。

 

解决办法:每次VARIANT中的内容取出来后,调用VariantClear() 将VARIANT清除就好了

相关文章
Echarts实战案例代码(19):利用visualMap视觉映射组件制作五色玫瑰工作进程图
Echarts实战案例代码(19):利用visualMap视觉映射组件制作五色玫瑰工作进程图
224 0
|
1天前
|
SQL 关系型数据库 MySQL
定时任务频繁插入数据导致锁表问题 -> 查询mysql进程
定时任务频繁插入数据导致锁表问题 -> 查询mysql进程
9 1
|
4月前
|
Python
在Python中,`multiprocessing`模块提供了一种在多个进程之间共享数据和同步的机制。
在Python中,`multiprocessing`模块提供了一种在多个进程之间共享数据和同步的机制。
后端登录接口使用postman,无法接收返回数据,怎样解决,认真比较与原项目的代码,看看有没有写的不一样的,问题就能解决,不要多少写,根据postman的提示先找到错误的进程,看错误进程出现在那个进程
后端登录接口使用postman,无法接收返回数据,怎样解决,认真比较与原项目的代码,看看有没有写的不一样的,问题就能解决,不要多少写,根据postman的提示先找到错误的进程,看错误进程出现在那个进程
|
6月前
|
存储 缓存 Linux
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
本文介绍了Xenomai中的XDDP(Xenomai Distributed Data Protocol)通信机制,XDDP用于实时和非实时进程之间的数据交换。XDDP在Xenomai内核中涉及的数据结构和管理方式,以及创建XDDP通道后的实时端和非实时端连接过程。
266 0
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
|
6月前
|
存储 缓存 监控
深度解析操作系统中的核心组件:进程管理与内存优化
【5月更文挑战第29天】 在现代计算技术的心脏,操作系统扮演着至关重要的角色。它不仅管理和控制计算机硬件资源,还为应用程序提供了一个运行环境。本文将深入探讨操作系统中的两个核心组件——进程管理和内存管理,并分析它们对系统性能的影响以及如何通过技术手段实现优化。通过对操作系统内部机制的剖析,我们将揭示这些组件是如何相互作用,以及它们如何共同提升系统的响应速度和稳定性。
|
6月前
|
负载均衡 网络协议 中间件
掌握 SOME/IP :访问进程数据 构建高效通信系统的关键技术
掌握 SOME/IP :访问进程数据 构建高效通信系统的关键技术
321 2
|
6月前
|
数据处理 数据安全/隐私保护
智能推荐映射关系,加速数据标准落地进程
在V4.0版本中,Dataphin推出了智能推荐映射关系功能,用户可以基于内置特征或创建自定义特征,对数据内容进行表示,并将其与数据标准关联,进而智能映射映射关系,尤其在字段分布广泛和命名多变的情况下,可以提高映射的准确性和效率,加速了数据标准实施。
298 0
|
11月前
|
存储 数据安全/隐私保护 Windows
4.5 Windows驱动开发:内核中实现进程数据转储
多数ARK反内核工具中都存在驱动级别的内存转存功能,该功能可以将应用层中运行进程的内存镜像转存到特定目录下,内存转存功能在应对加壳程序的分析尤为重要,当进程在内存中解码后,我们可以很容易的将内存镜像导出,从而更好的对样本进行分析,当然某些加密壳可能无效但绝大多数情况下是可以被转存的。
66 0
4.5 Windows驱动开发:内核中实现进程数据转储
|
消息中间件 大数据 Linux
Linux进程间通信:实现协作与数据交换的多种方式
多任务并发执行是一种常见的应用场景。在Linux操作系统中,进程间通信(Inter-Process Communication,IPC)是实现多任务协作与数据交换的关键技术。本文将介绍Linux中常用的IPC方式,包括管道、消息队列、共享内存和套接字。
379 0

相关实验场景

更多