asp.net下释入EXCEL COM问题!

henryfan1 2005-05-25 10:44:33
我在APS.net下调用Excel COM资源释放不了。
在WIN下同样的代码不存在这种问题。
我也从微软的站点下载了Microsoft Office XP PIA。
但是资源还是不能释放。
通过Marshal.ReleaseComObject和GC.Collect()也不能释放。
...全文
189 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
henryfan1 2005-05-25
  • 打赏
  • 举报
回复
其实MSDN上也有详细的解决方法。
奇怪的是,在windows下是没这种情况出现,在asp.net下就发生了。
看来还是通过XML或HTML来解决了
qingyun1020 2005-05-25
  • 打赏
  • 举报
回复
这么多的分啊,可是俺还不太会这个,给你顶了。
smx717616 2005-05-25
  • 打赏
  • 举报
回复
基本思想就是,只要你用过的对象 都必须通过

System.Runtime.InteropServices.Marshal.ReleaseComObject (oSheet);

释放。。。
smx717616 2005-05-25
  • 打赏
  • 举报
回复
参见这两个帖子:
http://community.csdn.net/Expert/topic/3486/3486601.xml?temp=.7558252

http://community.csdn.net/Expert/topic/3838/3838331.xml?temp=.4778101

你的问题基本上就能解决了。。。
goody9807 2005-05-25
  • 打赏
  • 举报
回复
Public Sub killExcelProcess()
'结束 Excel 进程
Dim xlProcess As New System.Diagnostics.Process

For Each xlProcess In System.Diagnostics.Process.GetProcesses
If xlProcess.ProcessName.ToUpper.Equals("EXCEL") Then
'结束 excel 进程
xlProcess.Kill()
End If
Next
End Sub
smx717616 2005-05-25
  • 打赏
  • 举报
回复
通过Marshal.ReleaseComObject和GC.Collect()也不能释放。

这样还不行的话,就杀进程吧。。。
henryfan1 2005-05-25
  • 打赏
  • 举报
回复
没有人遇到这情况,难道是我电脑问题?
lovinger2000 2005-05-25
  • 打赏
  • 举报
回复
这样吧,要不你去下载一下ExcelQuicker来看看吧,用那个导出Excel报表非常方便的,在www.eudev.net,如果有问题的话我们MSN上聊吧。MSN:eudev.net@yeah.net
另外,以上代码你的问题是什么?
henryfan1 2005-05-25
  • 打赏
  • 举报
回复

不知道我以下代码是否有没有写错。
string filename = Guid.NewGuid().ToString()+".xls";

Microsoft.Office.Interop.Excel.Application app = new
Microsoft.Office.Interop.Excel.Application();

Microsoft.Office.Interop.Excel.Workbook book = app.Workbooks.Open(System.Web.HttpContext.Current.Request.PhysicalApplicationPath+@"OutFiles\questionTemplate.xls",Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing) as Microsoft.Office.Interop.Excel.Workbook;

book.SaveAs(System.Web.HttpContext.Current.Request.PhysicalApplicationPath+@"OutFiles\"+filename
,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlShared,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
Microsoft.Office.Interop.Excel.Worksheet sheet = book.Sheets[1] as Microsoft.Office.Interop.Excel.Worksheet;


book.Save();
book.Close(false,null,null);
System.Runtime.InteropServices.Marshal.ReleaseComObject(book);
book = null;
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;
System.GC.Collect();
return filename;
lovinger2000 2005-05-25
  • 打赏
  • 举报
回复
Dear henryfan1(每天好心情(*_*)),
你在好好看看,在finally中怎么没有区别??释放的时候,只需要释放workbook和application对象就可以了,其实,执行顺序一定要如下,这是有一定原因的,改天我有时间了再写一篇文章,介绍其原理吧...

this.mWorkbook.Close(false, null, null);
System.Runtime.InteropServices.Marshal.ReleaseComObject(this.mWorkbook);
this.mWorkbook = null;

this.mApplication.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(this.mApplication);
this.mApplication = null;
henryfan1 2005-05-25
  • 打赏
  • 举报
回复
谢谢楼上
你看下我的代码就知道,应该和你所说的没什么分别。
string filename = Guid.NewGuid().ToString()+".xls";

Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbooks books = app.Workbooks;
Microsoft.Office.Interop.Excel.Workbook book = books.Open(System.Web.HttpContext.Current.Request.PhysicalApplicationPath+@"OutFiles\questionTemplate.xls"
,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,
Type.Missing,Type.Missing,Type.Missing) as Microsoft.Office.Interop.Excel.Workbook;
book.SaveAs(System.Web.HttpContext.Current.Request.PhysicalApplicationPath+@"OutFiles\"+filename
,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlShared,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
Microsoft.Office.Interop.Excel.Worksheet sheet = book.Sheets[1] as Microsoft.Office.Interop.Excel.Worksheet;
try
{
int row = 2;
string[] values;
foreach(System.Data.DataRow datarow in this.Items.Tables[0].Rows)
{
Microsoft.Office.Interop.Excel.Range range = sheet.get_Range("A"+row,"L"+ row) as Microsoft.Office.Interop.Excel.Range;
values = new string[]{
datarow[Entitys.YWQUESTIONSOjb.F_QUESTIONNO].ToString(),
datarow[Entitys.YWQUESTIONSOjb.F_PROVIDE].ToString(),
string.Format("{0:d}",datarow[Entitys.YWQUESTIONSOjb.F_PROVIDEDATE]),
string.Format("{0:d}",datarow[Entitys.YWQUESTIONSOjb.F_CONFIRMDATE]),
datarow[Entitys.YWQUESTIONSOjb.F_FUNCTIONBOUND].ToString(),
datarow[Entitys.YWQUESTIONSOjb.F_REMARK].ToString(),
datarow[Entitys.YWQUESTIONSOjb.F_SCHEDULE].ToString()+"%",
datarow[Entitys.YWQUESTIONSOjb.F_STATE].ToString(),
string.Format("{0:d}",datarow[Entitys.YWQUESTIONSOjb.F_INTENDDATE]),
string.Format("{0:d}",datarow[Entitys.YWQUESTIONSOjb.F_COMPETEDATE]),
"",
datarow[Entitys.YWQUESTIONSOjb.F_DEPICT].ToString()

};
range.Value2 = values;
row++;
int r1= System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
range = null;
values = null;
}

book.Save();
book.Close(false,Type.Missing,Type.Missing);
app.Quit();





}
catch(System.Exception e)
{
throw e;
}
finally
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet);
sheet = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(book);
book = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(books);
books = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
app = null;

System.GC.Collect();


}
return filename;
lovinger2000 2005-05-25
  • 打赏
  • 举报
回复
不知道你知道ExcelQuicker不,一个Excel报表控件,没有你所讲述的进程问题,其中释放内存的代码如下:
/// <summary>
/// Finilize resource, decrease reference and clear memory
/// </summary>
public void Dispose()
{
if(this.mWorkbook != null)
{
this.mWorkbook.Close(false, null, null);
System.Runtime.InteropServices.Marshal.ReleaseComObject(this.mWorkbook);
this.mWorkbook = null;
}

if(this.mApplication != null)
{
this.mApplication.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(this.mApplication);
this.mApplication = null;
}

GC.Collect();
}

控件是我写的,在www.eudev.net上可以下载(ExcelQuicker在一个半月内会拿到SourceForge.net去开源,现在正在更新英文注释和增加HTML报表的功能),根据我对Excel的深入了解,再次分享一下我的理解和推测:

原因是这样的:因为在.net下,内存管理是由GC统一的管理的,而GC的释放时间是不确定的,即使你调用GC.Collect(),它也只是告诉GC去检查无效资源并释放它们。

在Excel VBA操作中,托管堆上实际保存的是指向Excel资源的指针引用,而在ASP.NET中, 实际的应用程序不是你的项目工程,而是aspnet_wp,所以当你调用完后,甚至结束你的WEB程序时,进程不会释放,因为aspnet_wp对Excel进程有引用。

当你第一次构造Application时,是的的确确开辟了Excel进程对应的内存,并且对这个Excel进程的引用为1,在之后的Application对象构造,其实是增加对这个之前那个Excel COM的引用,当GC中会保存这份引用,但是当你使用完毕,GC是自动的去销毁了托管堆上的这份引用,但是却没有去减少对COM的引用,所以Excel的进程一直没法销毁。

但是,System.Runtime.InteropServices.Marshal.ReleaseComObject(this.mApplication);这句话其实就是让指向Excel的引用减1,再使用this.mApplication = null;以告诉之前this.mApplication引用的内存(GC中的内存)已经没有任何引用,根据GC的回收机制,这种内存才可以被回收,这时再命令GC回收。

上面的代码达到这样的效果,当你开启应用程序时,进程中会出现一个Excel进程,同时当你再构造了N多Application对象时,进程中会出现N多的Excel进程,而这些会在你的上述代码执行后立即结束,这个进程短时间不会消失的,即使你的操作完成,当时在一段时间后也会回收(这段时间不确定,因为GC的不确定)

而在Winform下,你关闭应用程序的一瞬间,该应用程序所涉及到的所有资源会被释放,所以在Winform下释放Excel进程一点问题也没有。你可以尝试在Winform下,在一个应用程序中连续生成N个Excel文件,其中释放方法只是Application对象的.Quit(),这样一样会有很多进程,而当你关闭应用程序时,进程就都结束了。

不懂的地方,请:
MSN:eudev.net@yeah.net

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

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