App Center Crashes (UWP/WinUI)
Important
Visual Studio App Center is scheduled for retirement on March 31, 2025. While you can continue to use Visual Studio App Center until it is fully retired, there are several recommended alternatives that you may consider migrating to.
App Center Crashes will automatically generate a crash log every time your app crashes. The log is first written to the device's storage and when the user starts the app again, the crash report will be sent to App Center. Collecting crashes works for both beta apps and those submitted to the Windows Store. Crash logs contain valuable information for you to help fix the crashes.
The App Center SDK collects only crashes caused by unhandled .NET exceptions. It doesn't collect native crashes e.g. when using C or C++. However, if you have an app with C++ crashes, you can upload them to App Center via the upload crashes API.
Follow the Getting Started section if you haven't set up the SDK in your application yet.
Note
Currently we don't support detection of low memory warnings on the UWP/WinUI platform.
- Open the console in Visual Studio. To do this, choose Tools > NuGet Package Manager > Package Manager Console.
- Type the following commands:
Install-Package Microsoft.AppCenter.Crashes
Add the appropriate namespaces before you use our APIs.
using Microsoft.AppCenter.Crashes;
Add or edit the following call to your application's constructor to include the crashes module:
AppCenter.Start("{Your App Secret}", typeof(Crashes));
App Center Crashes provides you with an API to generate a test crash for easy testing of the SDK. This API checks for debug vs release configurations. So you can only use it when debugging as it won't work for release apps.
Crashes.GenerateTestCrash();
App Center Crashes has two APIs that give you more information in case your app has crashed.
At any time after starting the SDK, you can check if the app crashed in the previous launch:
bool didAppCrash = await Crashes.HasCrashedInLastSessionAsync();
This comes in handy in case you want to adjust the behavior or UI of your app after a crash has occurred. Some developers choose to show additional UI to apologize to their users, or want a way to get in touch after a crash has occurred.
Note
This method must only be used after Crashes
has been started; it will always return false
before start.
If your app crashed previously, you can get details about the last crash.
ErrorReport crashReport = await Crashes.GetLastSessionCrashReportAsync();
Note
This method must only be used after Crashes
has been started; it will always return null
before start.
There are numerous use cases for this API, the most common one is people who call this API and implement their custom Crashes delegate or listener.
App Center Crashes provides callbacks for developers to perform additional actions before and when sending crash logs to App Center.
Note
Set the callback before calling AppCenter.Start()
, since App Center starts processing crashes immediately after the start.
Set this callback if you want to decide if a particular crash needs to be processed or not. For example, there could be a system level crash that you'd want to ignore and that you don't want to send to App Center.
Crashes.ShouldProcessErrorReport = (ErrorReport report) =>
{
// Check the report in here and return true or false depending on the ErrorReport.
return true;
};
If user privacy is important to you, you might want to get user confirmation before sending a crash report to App Center. The SDK exposes a callback that tells App Center Crashes to await user confirmation before sending any crash reports.
If you chose to do so, you're responsible for obtaining the user's confirmation, e.g. through a dialog prompt with one of the following options: Always Send, Send, and Don't send. Based on the input, you'll tell App Center Crashes what to do and the crash will then be handled accordingly.
Note
The SDK doesn't display a dialog for this, the app must provide its own UI to ask for user consent.
Note
The app shouldn't call NotifyUserConfirmation
explicitly if it doesn't implement a user confirmation dialog; the Crashes module will handle sending logs for you implicitly.
The following callback shows how to tell the SDK to wait for user confirmation before sending crashes:
Crashes.ShouldAwaitUserConfirmation = () =>
{
// Build your own UI to ask for user consent here. The 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;
};
In case you return true
in the callback above, your app must obtain (using your own code) user permission and message the SDK with the result using the following API.
// 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);
At times, you want to know the status of your app crash. A common use case is that you might want to show UI that tells the users that your app is submitting a crash report, or, in case your app is crashing quickly after the launch, you want to adjust the behavior of the app to make sure the crash logs can be submitted. App Center Crashes provides three different callbacks that you can use in your app to be notified of what's going on:
Crashes.SendingErrorReport += (sender, e) =>
{
// Your code, e.g. to present a custom UI.
};
In case we have network issues or an outage on the endpoint, and you restart the app, SendingErrorReport
is triggered again after process restart.
Crashes.SentErrorReport += (sender, e) =>
{
// Your code, e.g. to hide the custom UI.
};
Crashes.FailedToSendErrorReport += (sender, e) =>
{
// Your code goes here.
};
Receiving FailedToSendErrorReport
means a non-recoverable error such as a 4xx code occurred. For example, 401 means the appSecret
is wrong.
This callback isn't triggered if it's a network issue. In this case, the SDK keeps retrying (and also pauses retries while the network connection is down).
You can add binary and text attachments to a crash report. The SDK will send them along with the crash so that you can see them in App Center portal. The following callback will be invoked right before sending the stored crash from previous application launches. It won't be invoked when the crash happens. Be sure the attachment file is not named minidump.dmp
as that name is reserved for minidump files. Here is an example of how to attach text and an image to a crash:
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")
};
};
Note
The size limit is currently 7 MB. Attempting to send a larger attachment will trigger an error.
You can enable and disable App Center Crashes at runtime. If you disable it, the SDK won't do any crash reporting for the app.
Crashes.SetEnabledAsync(false);
To enable App Center Crashes again, use the same API but pass true
as a parameter.
Crashes.SetEnabledAsync(true);
You don't need to await this call to make other API calls (such as IsEnabledAsync
) consistent.
The state is persisted in the device's storage across application launches.
You can also check if App Center Crashes is enabled or not:
bool isEnabled = await Crashes.IsEnabledAsync();
App Center also allows you to track errors by using handled exceptions. To do so, use the TrackError
method:
try {
// your code goes here.
} catch (Exception exception) {
Crashes.TrackError(exception);
}
An app can optionally attach properties to a handled error report to provide further context. Pass the properties as a dictionary of key/value pairs (strings only) as shown in the example below.
try {
// your code goes here.
} catch (Exception exception) {
var properties = new Dictionary<string, string>
{
{ "Category", "Music" },
{ "Wifi", "On"}
};
Crashes.TrackError(exception, properties);
}
You can also optionally add binary and text attachments to a handled error report. Pass the attachments as an array of ErrorAttachmentLog
objects as shown in the example below.
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);
}