CrystalReport加载报告失败

我有一个使用Crystal Report 2008的Windows应用程序项目(C#和.NET 2.0)。但是在加载报告时有时会出现错误(似乎是偶然的)。 那个错误是:

CrystalDecisions.Shared.CrystalReportsException: Load report failed. System.Runtime.InteropServices.COMException (0x8000020D): Unable to load report. at CrystalDecisions.ReportAppServer.ClientDoc.ReportClientDocumentClass.Open(Object& DocumentPath, Int32 Options) at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.Open(Object& DocumentPath, Int32 Options) at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.EnsureDocumentIsOpened() --- End of inner exception stack trace --- at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.EnsureDocumentIsOpened() at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename, OpenReportMethod openMethod, Int16 parentJob) at CrystalDecisions.CrystalReports.Engine.ReportDocument.Load(String filename) at SIA.DataTransfer.Forms.frmReport.GetStateReport(Int32 transferType) 

请指导我。 我怎么解决这个问题?

如果您的应用程序是独立的可执行文件,则会生成此错误,因为在完成任何操作后,您没有正确关闭报表对象。 您可能会在应用程序中看到此错误作为ASP.NET应用程序运行,并且有许多用户同时访问您的站点。

您可以通过调整此注册表项来更快地显示错误:

 HKEY_LOCAL_MACHINE\SOFTWARE\CRYSTAL DECISIONS\10.0\REPORT APPLICATION SERVER\SERVER\PrintJobLimit 

它通常默认为75.对于调试,您可以将其设置为较小的值并导致错误更快出现。

完成使用报表对象后,请调用.Close()方法,该方法将清除所使用的未管理资源。

有些人提到将设置更改为-1。 这是一个错误,它只会导致长时间运行的应用程序出现其他问题。 该过程最终会耗尽资源,并以更难以排除故障的方式开始失败。

增加CurrentJobLimit不是解决方案; 如果计数器未重置,则会达到此数字。
若要避免作业计数器增加,您需要以编程方式关闭Crystal报表文档( ReportSource.Close() )。

 protected void Page_Unload(object sender, EventArgs e) { CrystalReportViewer1.ReportSource.Close(); } 

这是避免继续增加已打开报告的唯一方法,由CurrentJobLimit计算

我已经validation了John Dyer的解决方案, 上面 的解决方案并不适用于所有情况。

我还validation了重新安装Crystal Runtime对此特定错误没有任何好处。

对于我的应用程序,这只发生在Citrix安装的独立.exe上,带有嵌入式报告。 在使用Crystal Report Viewer之前,我需要确保根据John的说明清除了之前在查看器中加载的任何报告。 所以,我会写一些(在VB中)看起来像

 Public Function ShowRpt(...) As Boolean .... CleanOutViewer() .... End Function 

CleanOutViewer的位置是:

 Private Sub CleanOutViewer() If Not Me.CrystalReportViewer1.ReportSource() Is Nothing Then CType(Me.CrystalReportViewer1.ReportSource(), CrystalDecisions.CrystalReports.Engine.ReportDocument).Close() CType(Me.CrystalReportViewer1.ReportSource(), CrystalDecisions.CrystalReports.Engine.ReportDocument).Dispose() Me.CrystalReportViewer1.ReportSource() = Nothing GC.Collect() End If End Sub 

.Close()之后的调用也没有效果(并且作为尝试强制Crystal释放资源的替代尝试添加)。

Crystal Report Document需要手动处理。

您应该控制应用程序中所有报告的生命周期,并在达到75限制之前调用它们的Dispose。

如何在此链接中实现此目标有一个很好的方法:

http://geekswithblogs.net/technetbytes/archive/2007/07/17/114008.aspx

互联网还建议在您尝试打开报告的计算机上重新安装水晶报告运行时(确保所有位置具有相同的版本)。

仅供参考,我刚刚针对类似问题validation了此解决方案。 使用映射的网络共享或UNC路径时,ReportDocument.Load方法失败,并在文件服务器上安装晶体报告VS运行时修复了问题。