挥之不去的 Excel 进程
Lingering Excel Process
我正在做一个 Windows 服务,我正在使用 Microsoft.Office.Interop.Excel 创建一个新的 excel 文件,编辑它,然后保存它。
完成后,关闭相应的对象(工作表、工作簿),退出 excel 应用程序,并 Marshal 释放 COM 对象,这个过程仍然存在。
private void doWork()
{
var excelApp = new MsExcel.Application();
var workBooks = excelApp.Workbooks;
var workbook = excelApp.Workbooks.Add();
var sheets = workbook.Sheets;
_worksheet = workbook.Sheets[1];
//Do Work Here
_worksheet.SaveAs(filePath);
workbook.Close(false,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
workBooks.Close();
releaseObject(_worksheet);
releaseObject(sheets);
releaseObject(workbook);
releaseObject(workBooks);
excelApp.Quit();
releaseObject(excelApp);
}
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
_log.Error($"Unable to release object {obj} Error:" + ex.ToString());
obj = null;
}
finally
{
GC.Collect();
}
}
我看到其他一些建议释放对象的帖子,以及对 Workbooks 和 Sheets 的引用。不确定,为什么这仍然不起作用。
Microsoft 目前不推荐也不支持来自任何无人值守、非交互式客户端应用程序或组件(包括 ASP、ASP.NET、DCOM 和 NT)的 Microsoft Office 应用程序自动化服务),因为当 Office 在此环境中 运行 时,Office 可能表现出不稳定的行为 and/or 死锁。
如果您正在构建 运行 在服务器端上下文中的解决方案,您应该尝试使用已针对无人值守执行安全设置的组件。或者,您应该尝试找到至少允许 运行 客户端部分代码的替代方案。如果您从服务器端解决方案使用 Office 应用程序,该应用程序将缺少许多 运行 成功所必需的功能。此外,您将承担整体解决方案稳定性的风险。在 Considerations for server-side Automation of Office 文章中阅读更多相关信息。
作为解决方法,您可以考虑使用 One XML SDK 或为服务器端或服务执行设计的任何其他第三方组件。
您不应该调用 ReleaseComObject。那是很久以前就开始的老太太故事了,但是 it is incorrect。
如果您看到 excel 个实例仍然存在,这可能意味着您的程序在没有 运行 垃圾收集器和仍然保留到 com 对象的引用的情况下终止。解决问题的最佳方法是完全摆脱释放功能,然后在 doWork()
方法 returns.
之后调用 GC.Collect()
private void doWork()
{
try
{
doWorkImpl();
}
finally
{
GC.Collect(); //The GC collect needs to be here, after the scope of doWorkImpl ends.
GC.WaitForPendingFinalizers(); //The excel instance gets closedin the finalizer.
}
}
private void doWorkImpl()
{
var excelApp = new MsExcel.Application();
var workBooks = excelApp.Workbooks;
var workbook = excelApp.Workbooks.Add();
var worksheet = workbook.Sheets[1]; //This needs to be a local variable, not a class variable.
//Do Work Here
worksheet.SaveAs(filePath);
workbook.Close(false,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
workBooks.Close();
excelApp.Quit();
}
这应该会导致 excel 实例运行,只要没有抛出异常并且 excelApp.Quit()
被成功调用。
但是,如果您只使用 xlsx 文件而不是 xsl 文件,我会 高度 建议远离 com 互操作和只需使用 the SDK microsoft provides 直接与 .xlsx 文件交互。
我正在做一个 Windows 服务,我正在使用 Microsoft.Office.Interop.Excel 创建一个新的 excel 文件,编辑它,然后保存它。
完成后,关闭相应的对象(工作表、工作簿),退出 excel 应用程序,并 Marshal 释放 COM 对象,这个过程仍然存在。
private void doWork()
{
var excelApp = new MsExcel.Application();
var workBooks = excelApp.Workbooks;
var workbook = excelApp.Workbooks.Add();
var sheets = workbook.Sheets;
_worksheet = workbook.Sheets[1];
//Do Work Here
_worksheet.SaveAs(filePath);
workbook.Close(false,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
workBooks.Close();
releaseObject(_worksheet);
releaseObject(sheets);
releaseObject(workbook);
releaseObject(workBooks);
excelApp.Quit();
releaseObject(excelApp);
}
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
_log.Error($"Unable to release object {obj} Error:" + ex.ToString());
obj = null;
}
finally
{
GC.Collect();
}
}
我看到其他一些建议释放对象的帖子,以及对 Workbooks 和 Sheets 的引用。不确定,为什么这仍然不起作用。
Microsoft 目前不推荐也不支持来自任何无人值守、非交互式客户端应用程序或组件(包括 ASP、ASP.NET、DCOM 和 NT)的 Microsoft Office 应用程序自动化服务),因为当 Office 在此环境中 运行 时,Office 可能表现出不稳定的行为 and/or 死锁。
如果您正在构建 运行 在服务器端上下文中的解决方案,您应该尝试使用已针对无人值守执行安全设置的组件。或者,您应该尝试找到至少允许 运行 客户端部分代码的替代方案。如果您从服务器端解决方案使用 Office 应用程序,该应用程序将缺少许多 运行 成功所必需的功能。此外,您将承担整体解决方案稳定性的风险。在 Considerations for server-side Automation of Office 文章中阅读更多相关信息。
作为解决方法,您可以考虑使用 One XML SDK 或为服务器端或服务执行设计的任何其他第三方组件。
您不应该调用 ReleaseComObject。那是很久以前就开始的老太太故事了,但是 it is incorrect。
如果您看到 excel 个实例仍然存在,这可能意味着您的程序在没有 运行 垃圾收集器和仍然保留到 com 对象的引用的情况下终止。解决问题的最佳方法是完全摆脱释放功能,然后在 doWork()
方法 returns.
GC.Collect()
private void doWork()
{
try
{
doWorkImpl();
}
finally
{
GC.Collect(); //The GC collect needs to be here, after the scope of doWorkImpl ends.
GC.WaitForPendingFinalizers(); //The excel instance gets closedin the finalizer.
}
}
private void doWorkImpl()
{
var excelApp = new MsExcel.Application();
var workBooks = excelApp.Workbooks;
var workbook = excelApp.Workbooks.Add();
var worksheet = workbook.Sheets[1]; //This needs to be a local variable, not a class variable.
//Do Work Here
worksheet.SaveAs(filePath);
workbook.Close(false,System.Reflection.Missing.Value,System.Reflection.Missing.Value);
workBooks.Close();
excelApp.Quit();
}
这应该会导致 excel 实例运行,只要没有抛出异常并且 excelApp.Quit()
被成功调用。
但是,如果您只使用 xlsx 文件而不是 xsl 文件,我会 高度 建议远离 com 互操作和只需使用 the SDK microsoft provides 直接与 .xlsx 文件交互。