yoy*_*sef 8 c# com excel interop pia
可能重复:
如何在C#中正确清理Excel互操作对象
我在这里阅读了许多关于管理COM引用的其他线程,同时使用.Net-Excel互操作来确保Excel进程在退出时正确退出,到目前为止,这些技术已经运行良好,但我最近遇到了一个将新工作表添加到现有工作簿文件时出现问题.
下面的代码留下了僵尸Excel进程.
如果我将工作表添加到新创建的工作簿文件,它将退出正常.如果我运行除.Add()行之外的代码,它会退出.(我正在读取的现有文件是由注释掉的代码创建的空文件)
有任何想法吗?
//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();
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*Jon 13
我做了类似的事情.我创建一个Excel文件或打开一个现有的.我删除所有工作表并添加我自己的工作表.这是我用来确保关闭所有引用的代码:
workbook.Close(true, null, null);
excelApp.Quit();
if (newSheet != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(newSheet);
}
if (rangeSelection != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(rangeSelection);
}
if (sheets != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
}
if (workbook != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
}
if (excelApp != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
}
newSheet = null;
rangeSelection = null;
sheets = null;
workbook = null;
excelApp = null;
GC.Collect();
Run Code Online (Sandbox Code Playgroud)
我已经用很多不同的选项对它进行了测试,并没有让它失败.
我手头没有代码,但我确实遇到了类似的问题。如果我没记错的话,我最终检索了 Excel 实例的进程 ID,并杀死了它(在适当的等待时间之后,并且当其他方法失败时)。
我想我用过:
GetWindowThreadProcessId(通过P/Invoke)对excel对象的hwnd属性获取进程id,然后用于Process.GetProcessById获取进程对象。完成此操作后,我会调用Kill该流程。
编辑:我必须承认,这不是理想的解决方案,但如果您找不到未发布的流氓界面,那么这将以真正的蛋壳/大锤方式修复它。;)
EDIT2:您不必Kill立即调用流程对象...您可以先尝试调用Close,然后再诉诸Kill.
| 归档时间: |
|
| 查看次数: |
26766 次 |
| 最近记录: |