C#互操作:Excel进程增加新的工作表中现有的文件后不退出 [英] C# interop: excel process not exiting after adding new worksheet to existing file
问题描述
可能重复:结果
的如何正确清理在C#中的Excel 互操作对象
块引用>
我读过很多关于这里在使用.Net的Excel的互操作,以确保Excel进程正确退出后退出,到目前为止的技术管理COM引用其他线程已经工作得很好,但添加新的工作表到现有的工作簿文件时,我最近碰到一个问题就来了。
下面的代码留下了僵尸Excel进程。
如果我添加一个工作表到新创建的工作簿文件,它退出的罚款。如果我跑不包括
中的代码。新增()
行,它退出的罚款。 (现有的文件,我从阅读是被注释掉的代码创建一个空文件)
任何想法?
//使用Excel =的Microsoft.Office.Interop.Excel;
//使用System.Runtime.InteropServices;
公共静态无效AddTest()
{
字符串文件名= @C:\addtest.xls
对象M = Type.Missing;
Excel.Application excelapp =新Excel.Application();
如果(excelapp == NULL)抛出新的异常(无法启动Excel);
Excel.Workbooks WBS = excelapp.Workbooks;
//如果我创建一个新的文件,然后添加一个工作表,
//将正常退出(也就是说,如果你取消注释接下来的两行
//并注释掉下方。开()行):
//Excel.Workbook WB = wbs.Add(Excel.XlWBATemplate.xlWBATWorksheet);
//wb.SaveAs(filename,M,M,M,M,M
// Excel.XlSaveAsAccessMode.xlExclusive,
// M,M,M,M,M) ;
//但是如果我打开现有文件并添加一个工作表,
//它不会退出(叶练成僵尸进程)
Excel.Workbook WB = WBS。打开(文件名,
M,M,M,M,M,M
Excel.XlPlatform.xlWindows,
M,M,M,M,M,M,M);
Excel.Sheets张= wb.Worksheets;
//这是有问题的行:
Excel.Worksheet wsnew = sheets.Add(M,M,M,M)为Excel.Worksheet;
//N.B。如果我尝试在指定添加()以上
wb.Save的参数没有帮助();
wb.Close(M,M,M);
//矫枉过正做GC这么多次,但表明,不解决它
GC();
//清理COM引用
//改变这些所有FinalReleaseComObject并没有帮助
,同时(对Marshal.ReleaseComObject(wsnew)0){}
wsnew = NULL ;
而(对Marshal.ReleaseComObject(张)大于0){}
薄片=无效;
,同时(对Marshal.ReleaseComObject(WB)大于0){}
WB = NULL;
而(对Marshal.ReleaseComObject(WBS)大于0){}
WBS =无效;
的GC();
excelapp.Quit();
而(对Marshal.ReleaseComObject(excelapp)大于0){}
excelapp =无效;
的GC();
}
公共静态无效的GC()
{
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
System.GC.Collect();
System.GC.WaitForPendingFinalizers();
}
解决方案我没有代码的手,但我也遇到了类似的问题。
。如果我没有记错,我结束了检索的Excel实例的进程ID,并杀死它(等待后,当其他方法失败)。
我想我用:
GetWindowThreadProcessId
(通过p / Invoke的)对excel对象hWnd属性获取进程的ID,然后使用Process.GetProcessById
来获取进程对象。
一旦我做到了,我称之为杀死
上的进程。
编辑:我不得不承认,这不是理想的解决方案,但如果你不能找到流氓接口不被释放,那么这将修复它真正的蛋壳/大锤方式。 ;)
EDIT2:你不必叫
杀死
立即进程对象上...你可以第一次尝试调用关闭
之前诉诸杀死
。Possible Duplicate:
How to properly clean up Excel interop objects in C#I've read many of the other threads here about managing COM references while using the .Net-Excel interop to make sure the Excel process exits correctly upon exit, and so far the techniques have been working very well, but I recently came across a problem when adding new worksheets to an existing workbook file.
The code below leaves a zombie Excel process.
If I add a worksheet to a newly created workbook file, it exits fine. If I run the code excluding the
.Add()
line, it exits fine. (The existing file I'm reading from is an empty file created by the commented out code)Any ideas?
//using Excel = Microsoft.Office.Interop.Excel; //using System.Runtime.InteropServices; public static void AddTest() { string filename = @"C:\addtest.xls"; object m = Type.Missing; Excel.Application excelapp = new Excel.Application(); if (excelapp == null) throw new Exception("Can't start Excel"); Excel.Workbooks wbs = excelapp.Workbooks; //if I create a new file and then add a worksheet, //it will exit normally (i.e. if you uncomment the next two lines //and comment out the .Open() line below): //Excel.Workbook wb = wbs.Add(Excel.XlWBATemplate.xlWBATWorksheet); //wb.SaveAs(filename, m, m, m, m, m, // Excel.XlSaveAsAccessMode.xlExclusive, // m, m, m, m, m); //but if I open an existing file and add a worksheet, //it won't exit (leaves zombie excel processes) Excel.Workbook wb = wbs.Open(filename, m, m, m, m, m, m, Excel.XlPlatform.xlWindows, m, m, m, m, m, m, m); Excel.Sheets sheets = wb.Worksheets; //This is the offending line: Excel.Worksheet wsnew = sheets.Add(m, m, m, m) as Excel.Worksheet; //N.B. it doesn't help if I try specifying the parameters in Add() above wb.Save(); wb.Close(m, m, m); //overkill to do GC so many times, but shows that doesn't fix it GC(); //cleanup COM references //changing these all to FinalReleaseComObject doesn't help either while (Marshal.ReleaseComObject(wsnew) > 0) { } wsnew = null; while (Marshal.ReleaseComObject(sheets) > 0) { } sheets = null; while (Marshal.ReleaseComObject(wb) > 0) { } wb = null; while (Marshal.ReleaseComObject(wbs) > 0) { } wbs = null; GC(); excelapp.Quit(); while (Marshal.ReleaseComObject(excelapp) > 0) { } excelapp = null; GC(); } public static void GC() { System.GC.Collect(); System.GC.WaitForPendingFinalizers(); System.GC.Collect(); System.GC.WaitForPendingFinalizers(); }
解决方案I don't have the code to hand, but I did run into a similar problem. If I recall correctly, I ended up retrieving the process id of the excel instance, and killing it (after a suitable wait period, and when the other method failed).
I think I used:
GetWindowThreadProcessId
(via P/Invoke) on the excel object hwnd property to get the process id, and then usedProcess.GetProcessById
to get a process object. Once I'd done that, I'd callKill
on the process.EDIT: I have to admit, this isn't the ideal solution, but if you can't find the rogue interface that isn't being released, then this will fix it in true eggshell/sledgehammer fashion. ;)
EDIT2: You don't have to call
Kill
on the process object immediately... You could first try callingClose
before resorting toKill
.这篇关于C#互操作:Excel进程增加新的工作表中现有的文件后不退出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!