C#使用Microsoft.Office.Interop.Excel操作后Excel对象的释放问题

luxin10 2011-11-04 11:35:28
使用C#进行Excel开发时,使用代理模式后造成Excel的对象释放不掉的问题,代码如下:


public class ExcelHelper : IDisposable
{
public ExcelHelper()
{
this._application = new myExcel.Application();
this._application.Visible = false;
this._workbooks = this._application.Workbooks;
}

public Microsoft.Office.Interop.Excel.Workbook Open(string filePath)
{
this._workbooks.Open(filePath);
}
}


上面的代码使用
using(ExcelHelper excel=new ExcelHelper)
{},可以正常释放所有Excel对象并将Excel进程退出,但是使用下面的代码不能:


public partial class ExcelHelper : IDisposable
{
public ExcelHelper()
{
this._application = new comExcel.Application();
this._application.Visible = false;
this._application.DisplayAlerts = false;
this._application.AlertBeforeOverwriting = false;
this._workbooks = this._application.Workbooks;
}

public WorkBook CreateWorkBook(string filePath)
{
return new WorkBook(this._workBooks.Open(filePath));
}
}

public class WorkBook
{
private Microsoft.Office.Interop.Excel.Workbook workBook;
internal readonly object missing = System.Reflection.Missing.Value;

private WorkBook()
{ }

internal WorkBook(Microsoft.Office.Interop.Excel.Workbook _workBook)
{
this.workBook = _workBook;
}
}


上面的代码使用
using(ExcelHelper excel=new ExcelHelper)
{}
后,WorkBook类里面的私有成员private Microsoft.Office.Interop.Excel.Workbook workBook好像不能释放,导致Excel进程无法退出,这里该如何释放所有成员并正常退出Excel啊?
...全文
1989 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
yngaocn 2012-10-03
  • 打赏
  • 举报
回复
正遇到该问题,期望能解决
宝_爸 2011-11-09
  • 打赏
  • 举报
回复
Google到的

Excel does not quit because your app is still holding references to COM objects.

I guess you're invoking members of a COM object without assigning it to a variable.

For me it was the excelApp.Worksheets object I directly used without assigning it to a variable:

Worksheet sheet = excelApp.Worksheets.Open(...);
...
Marshal.ReleaseComObject(sheet);
What I didn't know was that internally C# created a wrapper for the Worksheets COM object which didn't get released by my code (because I wasn't aware of it) and was the cause why Excel was not unloaded.

I found the solution to my problem on this page, which also has a nice rule for the usage of COM objects in C#:

Never use 2 dots with com objects.

So with this knowledge the right way of doing the above is:

Worksheets sheets = excelApp.Worksheets; // <-- the important part
Worksheet sheet = sheets.Open(...);
...
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(sheet);

然后调用
xlBook(Workbooks类型).Close()和xlApp.Quit();

上面的资料来自:
http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c-sharp
OrangeEvan 2011-11-09
  • 打赏
  • 举报
回复
this._application = new myExcel.Application();
luxin10 2011-11-09
  • 打赏
  • 举报
回复
试过了,没用!呵呵
阿非 2011-11-09
  • 打赏
  • 举报
回复
试试在 Dispose() 方法中将

传入的Workbook 对象释放
luxin10 2011-11-09
  • 打赏
  • 举报
回复
本帖问题点数共计100分,本帖50分,还有另外一篇帖子一模一样50分,地址:http://topic.csdn.net/u/20111104/11/dab0fb70-45c1-4bcf-82f8-a64e03a01210.html?47685,哪个高手解决过类似的问题?请指点一二!100分全部送上!
luxin10 2011-11-09
  • 打赏
  • 举报
回复
谢谢大家!困扰了半个月的问题终于解决了,问题的症结还是在于在类中声明了com对象,但是在释放的时候没有释放完全,特别是比方说在一个集合类中声明了com对象,那么在该集合类中必须循环去释放掉所有的子类占用的com资源;谢谢Sandy945和findcaiyzh,给我了很大的帮助!
阿非 2011-11-09
  • 打赏
  • 举报
回复
用 findcaiyzh 找的文章中的写法。
阿非 2011-11-09
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 luxin10 的回复:]
试过了,没用!呵呵
[/Quote]

你怎么写的?
mabaolin 2011-11-04
  • 打赏
  • 举报
回复
http://blog.csdn.net/sunyou/archive/2005/08/22/461133.aspx
小赖赖 2011-11-04
  • 打赏
  • 举报
回复
呃,不止楼主这个情况
我在操作PPT中chart里面的Excel表格时候,时不时会抛远程COM不可控这样的异常,
然后就中断,这时候Excel和PowerPoint进程就不能释放,之后的所有操作全都抛异常
必须杀掉这2个进程才行
怀疑是Office组件互相调用间的漏洞
luxin10 2011-11-04
  • 打赏
  • 举报
回复
不需要kill进程,使用Dispose,清理Excel非托管资源后,使用GC回收一下,进程可以正常退出,我最上面的代码说了,只要不使用代理模式,清理资源退出进程没问题!
但是加了一个代理的WorkBook类后,类里面声明了private Microsoft.Office.Interop.Excel.Workbook workBook;私有变量,并且在实例化代理类时传入了Excel的_workBook对象,导致在ExcelHelper类清理Excel时,无法清理所有的Excel资源,导致Excel进程无法退出!
如果这种代理模式使用在Winform程序下,当Winform进程退出时,系统清理掉了代理WorkBook类的资源,此时Excle进程随着Winform进程一起退出,也就是说下面的代码在使用完Excel后进程不会马上退出,一定要等到Winform进程退出时Excel才会一起退出!
所以我想问清楚:怎么样能在使用完Excel资源后,主动清理上面的代码里面用到的所有Excel资源?只要资源能清理干净,Excel进程可以正常退出!
ijwsoft 2011-11-04
  • 打赏
  • 举报
回复

// 杀掉进程
public static void KillProcess(string processName)
{
System.Diagnostics.Process myproc = new System.Diagnostics.Process();
//得到所有打开的进程
try
{
foreach (Process thisproc in Process.GetProcessesByName(processName))
{
if (!thisproc.CloseMainWindow())
{
thisproc.Kill();
}
}
}
catch (Exception ex)
{
//throw new Exception("", Exc);
Common.DisplayMsg("系统错误", ex.Message);
}
}


调用方法:

Common.KillProcess("Excel");

111,124

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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