Windows) (App Center 崩溃

重要

Visual Studio App Center 计划于 2025 年 3 月 31 日停用。 虽然可以继续使用 Visual Studio App Center,直到它完全停用,但你可以考虑迁移到几个建议的替代方法。

详细了解支持时间线和替代方案。

每次应用崩溃时,App Center 崩溃都会自动生成崩溃日志。 日志首先写入设备的存储,当用户再次启动应用时,故障报告将发送到 App Center。

App Center SDK 仅收集由未经处理的 .NET 异常导致的崩溃。 它不会收集本机崩溃,例如使用 C 或 C++ 时。 但是,如果有 C++ 崩溃的应用,可以通过 上传崩溃 API 将其上传到 App Center。

如果尚未在应用程序中设置 SDK,请遵循 WPF/WinForms 入门

WinForms 应用程序上的未经处理的异常

注意

本部分和以下子部分仅适用于 WinForms。 如果要在 WPF 上集成 SDK,则可以跳过此部分。

默认情况下,WinForms 应用程序中未经处理的异常不会触发崩溃, (如果未附加调试器,则应用程序不会退出) 。

相反,Windows 向用户显示一个对话框,用于继续或退出应用执行。 因此,即使用户单击“ 退出 ”按钮) ,App Center SDK 也无法自动捕获这些异常 (。

仅当导致应用程序自动退出时,才会在 App Center 上收集崩溃。 App Center 仅支持每个会话一次崩溃。

可通过两种方法在 WinForms 中报告未经处理的异常。 可以将应用程序配置为在未经处理的异常时崩溃,或继续运行,但将未经处理的异常报告为运行时错误。

将应用程序配置为在崩溃时退出

这是将未经处理的异常报告为 App Center 崩溃 的唯一方法,使应用程序在未经处理的异常时退出。

为此,请在初始化 SDK 之前调用 Windows 方法:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
AppCenter.Start(...);

如果应用程序中不接受此选项,可以将未经处理的异常报告为运行时错误, (如下) 所述。

将未经处理的异常报告为运行时错误

如果应用程序必须在未经处理的异常后继续运行,则无法在 App Center 中将异常报告为 崩溃 ,但可以将其报告为 错误

为此,可以使用以下代码示例:

Application.ThreadException += (sender, args) =>
{
    Crashes.TrackError(args.Exception);
};
AppCenter.Start(...);

注意

附加调试器时,未经处理的异常将导致应用程序退出 (崩溃) 除非 将处理程序附加到 Application.ThreadException

生成测试崩溃

App Center 崩溃提供了一个 API,用于生成测试崩溃,以便轻松测试 SDK。 此 API 检查调试配置与发布配置。 因此,只能在调试时使用它,因为它不适用于发布应用。

Crashes.GenerateTestCrash();

获取有关以前崩溃的详细信息

App Center 崩溃有两个 API,可在应用崩溃时提供详细信息。

应用是否在上一个会话中崩溃?

启动 SDK 后,可以随时检查应用在上一次启动时崩溃:

bool didAppCrash = await Crashes.HasCrashedInLastSessionAsync();

如果想要在发生崩溃后调整应用的行为或 UI,这非常有用。 一些开发人员选择显示其他 UI 以向用户道歉,或者希望通过某种方式在崩溃发生后取得联系。

注意

此方法只能在启动后 Crashes 使用,它始终在启动前返回 false

有关上次崩溃的详细信息

如果你的应用以前崩溃,你可以获取有关上次崩溃的详细信息。

ErrorReport crashReport = await Crashes.GetLastSessionCrashReportAsync();

注意

此方法只能在启动后 Crashes 使用,它始终在启动前返回 null

此 API 有许多用例,最常见的用例是调用此 API 并实现其自定义 崩溃委托或侦听器的人员。

自定义 App Center 崩溃的用法

App Center 崩溃为开发人员提供回调,以便在将崩溃日志发送到 App Center 之前和向 App Center 发送时执行其他操作。

注意

在调用 AppCenter.Start()之前设置回调,因为 App Center 在启动后立即开始处理崩溃。

是否应处理崩溃?

如果要确定是否需要处理特定故障,请设置此回调。 例如,你可能希望忽略系统级别崩溃,并且不希望发送到 App Center。

Crashes.ShouldProcessErrorReport = (ErrorReport report) =>
{
    // Check the report in here and return true or false depending on the ErrorReport.
    return true;
};

如果用户隐私对你很重要,你可能希望在将崩溃报告发送到 App Center 之前获得用户确认。 SDK 公开一个回调,告知 App Center 崩溃在发送任何故障报告之前等待用户确认。

如果选择这样做,则你负责获取用户的确认,例如,通过对话框提示并使用以下选项之一: 始终发送发送不发送。 根据输入,你将告诉 App Center 崩溃要执行的操作,然后会相应地处理崩溃。

注意

SDK 不显示此对话框,应用必须提供自己的 UI 以请求用户同意。

注意

如果应用未实现用户确认对话框,则不应显式调用 NotifyUserConfirmation ;崩溃模块将隐式处理发送日志。

以下回调演示如何告诉 SDK 在发送崩溃之前等待用户确认:

Crashes.ShouldAwaitUserConfirmation = () =>
{
    // Build your own UI to ask for user consent here. SDK doesn't provide one by default.

    // Return true if you built a UI for user consent and are waiting for user input on that custom UI, otherwise false.
    return true;
};

如果你在上述回调中返回 true ,则应用必须使用自己的代码) 用户权限获取 (,并使用以下 API 向 SDK 发送结果消息。

// Depending on the user's choice, call Crashes.NotifyUserConfirmation() with the right value.
Crashes.NotifyUserConfirmation(UserConfirmation.DontSend);
Crashes.NotifyUserConfirmation(UserConfirmation.Send);
Crashes.NotifyUserConfirmation(UserConfirmation.AlwaysSend);

获取有关崩溃日志的发送状态的信息

有时,你想知道应用崩溃的状态。 一个常见的用例是,你可能想要显示 UI 来告知用户你的应用正在提交崩溃报告,或者,如果你的应用在启动后快速崩溃,你需要调整应用的行为,以确保可以提交崩溃日志。 App Center 崩溃提供了三个不同的回调,你可以在应用中使用这些回调来通知所发生的情况:

在 SDK 发送崩溃日志之前,将调用以下回调

Crashes.SendingErrorReport += (sender, e) =>
{
    // Your code, e.g. to present a custom UI.
};

如果终结点出现网络问题或中断,并且重启应用, SendingErrorReport 则会在进程重启后再次触发。

SDK 成功发送崩溃日志后,将调用以下回调

Crashes.SentErrorReport += (sender, e) =>
{
    // Your code, e.g. to hide the custom UI.
};

如果 SDK 未能发送故障日志,将调用以下回调

Crashes.FailedToSendErrorReport += (sender, e) =>
{
    // Your code goes here.
};

接收 FailedToSendErrorReport 表示发生了不可恢复的错误,例如 4xx 代码。 例如, 401 表示 appSecret 错误。

如果这是网络问题,则不会触发此回调。 在这种情况下,SDK 会继续重试 (,并在网络连接关闭) 时暂停重试。

向崩溃报告添加附件

可以将二进制附件和文本附件添加到崩溃报告。 SDK 会连同崩溃一起发送它们,以便你可以在 App Center 门户中看到它们。 在从以前的应用程序启动时发送存储的故障之前,将立即调用以下回调。 发生崩溃时,不会调用它。 确保 附件文件未 命名 minidump.dmp ,因为该名称是为小型转储文件保留的。 下面是如何将文本和图像附加到崩溃的示例:

Crashes.GetErrorAttachments = (ErrorReport report) =>
{
    // Your code goes here.
    return new ErrorAttachmentLog[]
    {
        ErrorAttachmentLog.AttachmentWithText("Hello world!", "hello.txt"),
        ErrorAttachmentLog.AttachmentWithBinary(Encoding.UTF8.GetBytes("Fake image"), "fake_image.jpeg", "image/jpeg")
    };
};

注意

大小限制当前为 7 MB。 尝试发送较大的附件将触发错误。

在运行时启用或禁用 App Center 崩溃

可以在运行时启用和禁用 App Center 崩溃。 如果禁用它,SDK 不会为应用执行任何崩溃报告。

Crashes.SetEnabledAsync(false);

若要再次启用 App Center 崩溃,请使用同一 API,但作为参数传递 true

Crashes.SetEnabledAsync(true);

无需等待此调用, (其他 API 调用(例如 IsEnabledAsync) 一致)。

状态在应用程序启动时保留在设备的存储中。

检查是否启用了 App Center 崩溃

还可以检查是否启用 App Center 崩溃:

bool isEnabled = await Crashes.IsEnabledAsync();

已处理错误

App Center 还允许使用已处理的异常来跟踪错误。 为此,请使用 TrackError 方法:

try {
    // your code goes here.
} catch (Exception exception) {
    Crashes.TrackError(exception);
}

应用可以选择性地将属性附加到已处理的错误报告,以提供进一步的上下文。 将属性作为键/值对的字典传递, (字符串仅) ,如以下示例所示。

try {
    // your code goes here.
} catch (Exception exception) {
    var properties = new Dictionary<string, string>
    {
        { "Category", "Music" },
        { "Wifi", "On"}
    };
    Crashes.TrackError(exception, properties); 
}

还可以选择将二进制和文本附件添加到已处理的错误报告。 将附件作为对象的数组 ErrorAttachmentLog 传递,如以下示例所示。

try {
    // your code goes here.
} catch (Exception exception) {
    var attachments = new ErrorAttachmentLog[]
    {
        ErrorAttachmentLog.AttachmentWithText("Hello world!", "hello.txt"),
        ErrorAttachmentLog.AttachmentWithBinary(Encoding.UTF8.GetBytes("Fake image"), "fake_image.jpeg", "image/jpeg")
    };
    Crashes.TrackError(exception, attachments: attachments);
}