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 }
大家好,我这边也写了一个程序,在32位机windows server 2003中测试通过了,在服务器windows server 2008中,该程序通过不了,只能够第一次成功,第二次就提示该文件正在被使用。我释放资源的代码如下: public void Close()//关闭一个Excel对象,销毁对象 { //wb.Save(); wb.Close(Type.Missing, Type.Missing, Type.Missing);
{
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
}
这个方法我看过,关键是怎么传参?我打开的Excel是根据一个路径,如:C:\test.xls
怎么写?
object objmissing = System.Reflection.Missing.Value;Excel.ApplicationClass application = new ApplicationClass();
Excel.Workbook book = application.Workbooks.Add(objmissing);
Excel.Worksheet sheet = (Excel.Worksheet)book.Worksheets.Add(objmissing,objmissing,objmissing,objmissing);//操作过程 ^&%&×&……&%&&……//释放
sheet.SaveAs(path,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing,objmissing);
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)sheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)book);
application.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject((object)application);
System.GC.Collect();有一点,在网上你是找不到滴···纯属经验:
如果你要写的Excel是多个Sheet的话,那么你最好写个函数:
比如 private bool overdue_report_sub(Excel.Worksheet sheet)
将sheet的对象传进去,在这个函数中进行操作,函数过程只写Sheet的操作过程,释放还是放在外面。如果你不这样做的话,那么,恭喜你,你还是释放不掉。但是如果只有一个Sheet操作的话,你就可以不用写这个函数了,只是在整个函数体中进行创建和释放。
我用的是在Winform中,通过Webbrowser打开已经存在得Excel
我打开的Excel是根据一个路径,如:C:\test.xls
this.webbrowser1.Navegage("C:\test.xls");
在进程里就有了,Excel.exe进程,如何关闭它!~
Excel.ApplicationClass xlsApp = null;
Excel.Workbook xlsBook = null;
Excel.Worksheet xlsSheet = null;try
{
xlsApp = new Excel.ApplicationClass();
xlsApp.AlertBeforeOverwriting = false;
xlsApp.DisplayAlerts = false; xlsBook = xlsApp.Workbooks.Open(excelFile, Missing.Value, Missing.Value, Missing.Value, pswStr, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); xlsBook.SaveAs(excelFileName, Missing.Value, "", Missing.Value, Missing.Value, Missing.Value, Excel.XlSaveAsAccessMode.xlNoChange, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
}
catch (Exception err)
{
MessageBox.Show("操作Excel文件异常: " + Environment.NewLine + err.Message);
}
finally
{
xlsSheet = null; if (xlsBook != null)
{
xlsBook.Close(false, Missing.Value, Missing.Value);
xlsBook = null;
} if (xlsApp != null)
{
xlsApp.Quit();
xlsApp = null;
}
}上面代码中,excelFile为需要打开的文件,excelFileName为要保存的文件,pswStr为打开Excel文件的口令。另存是不保存口令。
Excel.ApplicationClass xlsApp = null;
Excel.Workbook xlsBook = null;
Excel.Worksheet xlsSheet = null;我只是用webbrowser1打开了一个test.xls而已,在进程里就有了Excel.exe进程,如何关闭它!(不采用p.kill(),因为这样可能关闭其他的Excel进程)
private void button1_Click(object sender,EventArgs e)
{
this.openFileDialog1.ShowDialog();
this.webbrowser1.Navigate(this.openFileDialog1.FileName);
}
首先找到Excel进程开始调入内存的地方,你的程序中可能在 (webbrowser.Navagate(path))处,
用数组记录下此时所有的Excel 进程的进程号(或这些进程的标志)(这个数组有可能为空,也有可能不是)
然后,执行下一步程序产生新的Excel,用另一个数组记录此时的所有Excel的进程号,
比对这两个数组的内容就知道刚才产生的进程号是什么了,
然后再kill 掉这个进程就可以了
{
Process [] xlProcess= Process.GetProcessesByName("Excel");
foreach(Process tProcess in xlProcess)
{
tProcess.Kill();
}
}
catch(Exception exp2)
{
MessageBox.Show(exp2.ToString());
}
通过webbrowser控件打开一个test.xls后,如何捕捉其在进程中生成的PID,因为每个进程的PID是唯一的,我可以根据PID来Kill杀死它!~~
那位大侠能帮我解决哈,谢谢了!~~~
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
他们的一引用针存放在一个终结链表中(需要执行finalize),垃圾回收时会吧这些对象引用移动到终结可达队列,但这些对象还在GC堆上。
然后特殊的线程会清理终结可达队列,然后调用他们的finalize方法释放资源。等到下一次垃圾回收时,已经没有引用了,然后才会执行垃圾回收,回收这些对象。我程序中用dispose();来关闭资源,但是还是无法回收
后来是用了GC.ReRegisterForFinalize(webbrowers);这个是请求系统调用webbrowers的finalize方法。这样就可以关闭,这个效果和GC.Collect()以及关闭程序是一样的,另外一种方法是关闭后新建多个对象,使得系因为0代被填充满而进行垃圾回收,这个时候就会关闭。因为他们都会导致finalize方法执行。所以没有回收应该是finalize没有执行的原因。不知道我说的对不对!
因为没有对对象执行垃圾回收所以没有调用到Finalize方法,也就无法释放非托管资源。这是MSDN上写的Dispose写的:
每次释放对 Component 的最后一个引用前,均应调用 Dispose。否则,在垃圾回收器调用 Component 对象的 Finalize 方法之前,正在使用的资源不会被释放。他的意思也是调用了Dispose应该可以回收的,但这里没有回收,个人觉得可能是webbrowers这里写的有点问题。具体可以看MSDN上“清理非托管资源 ”,垃圾回收 框架设计上介绍的比较清楚
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天都没有搞定了,郁闷中
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();
}