C# winform 打开 Excel 后,如何释放其占用的资源?

zhouge_IT 2008-11-17 11:26:40
在winform中用webbrowser打开一个Excel后,(webbrowser.Navagate(path))无法释放进程里的Excel.exe资源,怎么办?
不能使用进程 process.kill(Excel.exe);因为这样会关闭其它的Excel进程
...全文
2145 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
simaxingyun 2011-12-16
  • 打赏
  • 举报
回复
你试试这个代码。。。。。。。。。。。
finally {
worksheet = null;
wb.Close(Type.Missing, Type.Missing, Type.Missing);
wbs.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wbs);
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
wbs = null;
wb = null;
app = null;
GC.Collect();
}
kg_loveyou2 2011-10-27
  • 打赏
  • 举报
回复
没有一个人弄清楼主的意思
xuok454 2011-04-07
  • 打赏
  • 举报
回复
大家好,我这边也写了一个程序,在32位机windows server 2003中测试通过了,在服务器windows server 2008中,该程序通过不了,只能够第一次成功,第二次就提示该文件正在被使用。我释放资源的代码如下:
public void Close()//关闭一个Excel对象,销毁对象
{
//wb.Save();
wb.Close(Type.Missing, Type.Missing, Type.Missing);

wbs.Close();
app.Workbooks.Close();
app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wbs);
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

wb = null;
wbs = null;
app = null;

GC.Collect();
}
发现了这个问题后,我发现程序的进行为:excel.exe *32,我就写了一个杀死该进程的程序,代码如下:
public static void killProcess(string processName)
{
foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcesses())
{
if (p.ProcessName.Trim ().ToLower().Equals(processName.Trim () .ToLower ()))
{
p.Kill();
}
}
}
结果是能够把excel.exe *32进程给杀掉,但是还是一样提示该文件正在被使用,我就直接从系统中删除该文件,结果搞w3wp.exe正在使用该文件,不知道大家见过该问题没有,各位帮帮忙啊,这个问题我已经3天都没有搞定了,郁闷中
zhouge_IT 2008-11-17
  • 打赏
  • 举报
回复
写下具体代码嘛!谢谢!~~~
luluyy 2008-11-17
  • 打赏
  • 举报
回复
用流的方式把excel中的数据导入webbrowser

zhouge_IT 2008-11-17
  • 打赏
  • 举报
回复
楼上的仁兄,public static void Kill(Microsoft.Office.Interop.Excel.Application excel)
这个方法我看过,关键是怎么传参?我打开的Excel是根据一个路径,如:C:\test.xls
怎么写?
human_2 2008-11-17
  • 打赏
  • 举报
回复
public static void Kill(Microsoft.Office.Interop.Excel.Application excel)
{
IntPtr t = new IntPtr(excel.Hwnd); //得到这个句柄,具体作用是得到这块内存入口

int k = 0;
GetWindowThreadProcessId(t, out k); //得到本进程唯一标志k
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(k); //得到对进程k的引用
p.Kill(); //关闭进程k
}
  • 打赏
  • 举报
回复
kill掉execel的那个进程。就全部释放了。
yilanwuyu123 2008-11-17
  • 打赏
  • 举报
回复
楼主是怎么操作这个Excel的

代码内打开就close掉

进程开的就Abort
cc_net 2008-11-17
  • 打赏
  • 举报
回复
Finalize是CRL提供的一个机制, 它保证如果一个类实现了Finalize方法,那么当该类对象被垃圾回收时,垃圾回收器会调用Finalize方法.而该类的开发者就必须在Finalize方法中处理 非托管资源的释放. 但是什么时候会调用Finalize由垃圾回收器决定,该类对象的使用者(客户)无法控制.从而无法及时释放掉宝贵的非托管资源.由于非托管资源是比较宝贵了,所以这样会降低性能.

Dispose(bool disposing)不是CRL提供的一个机制, 而仅仅是一个设计模式(作为一个IDisposable接口的方法),它的目的是让供类对象的使用者(客户)在使用完类对象后,可以及时手动调用非托管资源的释放,无需等到该类对象被垃圾回收那个时间点.这样类的开发者就只需把原先写在Finalize的释放非托管资源的代码,移植到Dispose(bool disposing)中. 而在Finalize中只要简单的调用 "Dispose(false)"就可以了.


因为没有对对象执行垃圾回收所以没有调用到Finalize方法,也就无法释放非托管资源。

这是MSDN上写的Dispose写的:
每次释放对 Component 的最后一个引用前,均应调用 Dispose。否则,在垃圾回收器调用 Component 对象的 Finalize 方法之前,正在使用的资源不会被释放。

他的意思也是调用了Dispose应该可以回收的,但这里没有回收,个人觉得可能是webbrowers这里写的有点问题。具体可以看MSDN上“清理非托管资源 ”,垃圾回收 框架设计上介绍的比较清楚
cc_net 2008-11-17
  • 打赏
  • 举报
回复
我写的多标签的浏览器试过了,关闭一个标签后,GC.Collect()下就关闭了

如果不执行就一直关闭不了,可能是没有执行finalize,而且我们不能直接调用对象的finalize方法

对于非托管资源的对象回收:
他们的一引用针存放在一个终结链表中(需要执行finalize),垃圾回收时会吧这些对象引用移动到终结可达队列,但这些对象还在GC堆上。
然后特殊的线程会清理终结可达队列,然后调用他们的finalize方法释放资源。等到下一次垃圾回收时,已经没有引用了,然后才会执行垃圾回收,回收这些对象。

我程序中用dispose();来关闭资源,但是还是无法回收
后来是用了GC.ReRegisterForFinalize(webbrowers);这个是请求系统调用webbrowers的finalize方法。这样就可以关闭,这个效果和GC.Collect()以及关闭程序是一样的,另外一种方法是关闭后新建多个对象,使得系因为0代被填充满而进行垃圾回收,这个时候就会关闭。

因为他们都会导致finalize方法执行。所以没有回收应该是finalize没有执行的原因。不知道我说的对不对!

qinhl99 2008-11-17
  • 打赏
  • 举报
回复

System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheets);
System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet);
...
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
System.Runtime.InteropServices.Marshal.ReleaseComObject(range);
worksheets=null;
worksheet=null;
...
excelApp=null;
range=null;

把操作Excel文件用到的对象实例全部释放。
然后资源回收!
GC.Collect();

流用完后要关闭;word文档关闭要退出并nothing
hans_marke 2008-11-17
  • 打赏
  • 举报
回复
能先查下,哪些东西在占资源么?
hans_marke 2008-11-17
  • 打赏
  • 举报
回复
能先查下,哪些东西在占资源么?
zhouge_IT 2008-11-17
  • 打赏
  • 举报
回复
现在的问题可以简化成这样:
通过webbrowser控件打开一个test.xls后,如何捕捉其在进程中生成的PID,因为每个进程的PID是唯一的,我可以根据PID来Kill杀死它!~~
那位大侠能帮我解决哈,谢谢了!~~~
abcyzq 2008-11-17
  • 打赏
  • 举报
回复
关注。
zhouge_IT 2008-11-17
  • 打赏
  • 举报
回复
楼上的仁兄,我说过不能通过进程名,来kill的,因为我不想杀死计算机中其他的Excel进程!~
techsky 2008-11-17
  • 打赏
  • 举报
回复
时间关系,只能给你些参考代码

try
{
Process [] xlProcess= Process.GetProcessesByName("Excel");
foreach(Process tProcess in xlProcess)
{
tProcess.Kill();
}
}
catch(Exception exp2)
{
MessageBox.Show(exp2.ToString());
}

gtiroy 2008-11-17
  • 打赏
  • 举报
回复
学习~!
techsky 2008-11-17
  • 打赏
  • 举报
回复
给你个解题思路吧,
首先找到Excel进程开始调入内存的地方,你的程序中可能在 (webbrowser.Navagate(path))处,
用数组记录下此时所有的Excel 进程的进程号(或这些进程的标志)(这个数组有可能为空,也有可能不是)
然后,执行下一步程序产生新的Excel,用另一个数组记录此时的所有Excel的进程号,
比对这两个数组的内容就知道刚才产生的进程号是什么了,
然后再kill 掉这个进程就可以了
加载更多回复(6)

111,082

社区成员

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

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

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