当我想显示报告但未安装 Crystal 报告时,如何捕获所有异常?

How can I catch all exceptions, when I want to show a report and Crystal reports is not installed?

我有一个工具,它从数据库中读取数据,修改它,然后将其显示在 crystal 报告中,该报告显示在单独的 window.

该工具有时会被没有安装 Crystal 报告的人使用,所以我想显示特定的错误消息,告诉用户确切的操作(而不是现在的通用消息).

我打电话给 window 报告如下:

try
{
    ReportWindow report = new ReportWindow(resultList);
    report.Show();
}
catch (Exception ex)
{
    this.LogAction("Could not open the report. To view it, you need to have Crystal Reports installed.", Notification.Error);
}

(为了这个问题简化了catch分支)

ReportWindow.xaml.cs

public ReportWindow(List<MeasureTestResult> measurement)
{
    this._measurementList = measurement;
    InitializeComponent();
}

ReportWindow.xaml

<Window x:Class="ResultFileViewer.Sources.ReportWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewer="clr-namespace:SAPBusinessObjects.WPF.Viewer;assembly=SAPBusinessObjects.WPF.Viewer">
    <viewer:CrystalReportsViewer Name="CrystalReportsViewer1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />    
</Window>

ReportWindow 构造函数中的行 InitializeComponent(); 抛出几个异常,例如 XamlParseExceptionInvalidCastException。问题是,只有 XamlParseException 被捕获。其他异常仅由我的 DispatcherUnhandledException 属性 或我的 App.xaml.

处理

这是有问题的,因为它要么意味着当e.Handled设置为false时整个应用程序被关闭,要么在用户关闭应用程序后仍然存在僵尸进程,当e.Handled是设置为真。

如何在调用报告 window 的 class 中捕获当前未处理的异常?

我尝试了 this solution,但也没有捕捉到 InvalidCastException

我已经放弃尝试捕获流氓异常,因为我没有成功。 相反,如果安装了 Crystal Reports,我会尝试预先检测。我基本上找到了两个选择:

  • 检查注册表中的特定条目
  • 如果需要的程序集存在,请检查全局程序集缓存 (GAC)

注册表检查有一个缺点,它只包含一个相当通用的名称而不是特定的版本条目(例如 HKEY_CURRENT_USER\Software\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0)。 此外,如果您事先安装了 Crystal Reports 并卸载了它,无论出于何种原因,注册表项都会保留,因此也无法可靠地检查是否安装了 Crystal Reports。

所以我进行了 GAC 检查,我是这样做的:

try
{
    // 13.0.2000.0 is Crystal Reports for VS 2010
    // the first assembly is the most important one, but it also gets deployed by the project itself
    // because of this I picked two additional assemblies to check for
    var a = System.Reflection.Assembly.Load("CrystalDecisions.CrystalReports.Engine, Version=13.0.2000.0, Culture=neutral,PublicKeyToken=692fbea5521e1304");
    result = a != null;
    a = System.Reflection.Assembly.Load("CrystalDecisions.CrystalReports.TemplateEngine, Version=13.0.2000.0, Culture=neutral,PublicKeyToken=692fbea5521e1304");
    result &= a != null;
    a = System.Reflection.Assembly.Load("CrystalDecisions.Windows.Forms, Version=13.0.2000.0, Culture=neutral,PublicKeyToken=692fbea5521e1304");
    result &= a != null;
}
catch (FileNotFoundException ex)
{
    this.LogAction("Could not open the report. To view it, you need to have Crystal Reports v13.0.12 (32-bit only) installed.");
    result = false;
}
catch
{
    //Runtime is in GAC but something else prevents it from loading. (bad install?, etc)
    result = false;
}

按预期工作。