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 Reportドキュメント(ReportSource.Close()
)をプログラムで閉じる必要があります。
protected void Page_Unload(object sender, EventArgs e)
{
CrystalReportViewer1.ReportSource.Close();
}
これは、CurrentJobLimit
によってカウントされる開かれたレポートの継続的な増加を回避する唯一の方法です。
John Dyer's ソリューション 上記 がすべての場合に機能するとは限らないことを確認しました。
また、Crystal Runtimeを再インストールしても、この特定のエラーには効果がないことも確認しました。
私のアプリの場合、これは、レポートが埋め込まれたスタンドアロンの.exeのCitrixインストールでのみ発生していました。 Crystal Report Viewerを使用する前に、Johnの指示に従って、以前にViewerにロードされたレポートをすべてクリアしたことを確認する必要があります。だから、私は(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 ReportDocumentは手動で破棄する必要があります。
アプリケーション内のすべてのレポートの有効期間を制御し、75の制限に達する前にそれらのレポートを呼び出す必要があります。
このリンクでこれを達成する方法についての良いアプローチがあります:
http://geekswithblogs.net/technetbytes/archive/2007/07/17/114008.aspx
インターネットでは、レポートを開こうとしているマシンにCrystal Reportランタイムを再インストールすることも提案されています(すべての場所のバージョンが同じであることを確認してください)。
参考までに、同様の問題についてこのソリューションを検証しました。マップされたネットワーク共有またはUNCパスを使用し、ファイルサーバーにCrystal Reports VSランタイムをインストールすると、ReportDocument.Loadメソッドが失敗し、問題が修正されました。