我们有一个 Web 应用程序,可以生成 Excel 电子表格并在服务器端运行宏。然后它通过电子邮件将它们发送给不同的人。它是传统报告风格的一部分,我们正在对其进行转换,但仍然支持我们作为 IIS 中的网站提供的新应用程序。
我知道进行 Office 自动化是一种不好的做法,因为我从 Microsoft 看到信息表明不支持此操作。这里的答案中也指出了打开 Excel 错误:System.Runtime.InteropServices.COMException (0x80080005):正在检索具有 CLSID 的组件的 COM 类工厂 https://stackoverflow.com/questions/14716047/opening-excel-error-system-runtime-interopservices-comexception-0x80080005-r
无论如何,简而言之,Excel 报告是在批处理场景中生成的,可以生成 3 到 300 份报告发送给不同的人。报告生成工作正常,直到到达第 15 到 20 项左右,然后它就崩溃了,它给了我下面的错误
System.Runtime.InteropServices.COMException (0x80080005): Retrieving the COM class factory for component with CLSID {00024500-0000-0000-C000-000000000046} failed due to the following error: 80080005 Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)).
at System.Runtime.Remoting.RemotingServices.AllocateUninitializedObject(RuntimeType objectType)
at System.Runtime.Remoting.Activation.ActivationServices.CreateInstance(RuntimeType serverType)
at System.Runtime.Remoting.Activation.ActivationServices.IsCurrentContextOK(RuntimeType serverType, Object[] props, Boolean bNewObj)
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at Ci.Infrastructure.Reporting.ReportProviderExcel.RunReport()
可能出了什么问题?第一份报告成功,我知道它不是 Excel 模板,因为当我再次重新运行它时,所有失败的报告都会成功继续,并且当生成第 15 到 20 个报告时,它会再次抛出错误。
更新:我们知道我们是在自找麻烦,但我需要一个解决方案来解决这个问题。请记住,这是针对遗留的东西,我们将来将停止支持这些东西,但在过渡时期我们需要它发挥作用。
我们尝试了序列化仍然不起作用。
我们尝试在遇到 COM 异常时休眠生成 Excel 报告的线程,它可以工作,但这不是一个优雅的结果。解决这个问题的任何好的解决方案都将获得赏金。
另一个更新:
通过在finally块上执行此操作来解决
finally
{
if (dataWorksheet != null)
{
Marshal.ReleaseComObject(dataWorksheet);
}
if (worksheets != null)
{
Marshal.ReleaseComObject(worksheets);
}
if (workbook != null)
{
workbook.Close(false);
Marshal.ReleaseComObject(workbook);
}
if (workbooks != null)
{
workbooks.Close();
Marshal.ReleaseComObject(workbooks);
}
if (excel != null)
{
excel.Quit();
Marshal.ReleaseComObject(excel);
}
}
就像马克沃尔斯所说的将每个 excel 实例作为一个工作单元关闭在再次使用之前完全清除 EXCEL 进程。