App Center stürzt ab (macOS)
Wichtig
Visual Studio App Center wird am 31. März 2025 eingestellt. Sie können Visual Studio App Center zwar weiterhin verwenden, bis es vollständig eingestellt ist, es gibt jedoch mehrere empfohlene Alternativen, zu denen Sie eine Migration in Betracht ziehen können.
App Center-Abstürze generieren automatisch ein Absturzprotokoll, wenn Ihre App abstürzt. Das Protokoll wird zuerst in den Speicher des Geräts geschrieben, und wenn der Benutzer die App erneut startet, wird der Absturzbericht an App Center gesendet. Das Sammeln von Abstürze funktioniert sowohl für Beta- als auch für Live-Apps, d. h. für solche, die an die App Store übermittelt werden. Absturzprotokolle enthalten wertvolle Informationen zur Behebung des Absturzes.
Befolgen Sie den Abschnitt Erste Schritte, wenn Sie das SDK noch nicht in Ihrer Anwendung eingerichtet haben.
Darüber hinaus erfordern Absturzprotokolle unter macOS symbolische Zeichen. Lesen Sie die App Center-Diagnosedokumentation , in der erläutert wird, wie Symbole für Ihre App bereitgestellt werden.
Hinweis
In der 4.0.0
Version von App Center wurden breaking changes eingeführt. Befolgen Sie den Abschnitt Migrieren zum App Center SDK 4.0.0 und höher , um App Center von früheren Versionen zu migrieren.
Absturzberichte in Erweiterungen
App Center unterstützt Absturzberichte in macOS-Erweiterungen. Die Verwendung ist identisch mit der in der Containeranwendung.
Generieren eines Testabsturzes
App Center Crashes bietet Ihnen eine API zum Generieren eines Testabsturzes zum einfachen Testen des SDK. Diese API kann nur in Test-/Beta-Apps verwendet werden und führt in Produktions-Apps keine Aktionen aus.
[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()
Weitere Informationen zu einem vorherigen Absturz
App Center-Abstürze verfügt über zwei APIs, die Ihnen weitere Informationen für den Fall liefern, dass Ihre App abgestürzt ist.
Hat die App in der vorherigen Sitzung eine Warnung zu wenig Arbeitsspeicher erhalten?
Nach dem Starten des SDK können Sie jederzeit überprüfen, ob die App in der vorherigen Sitzung eine Speicherwarnung erhalten hat:
[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession
Hinweis
Diese Methode darf nur verwendet werden, nachdem Crashes
sie gestartet wurde. Sie wird immer zurückgegeben NO
oder false
vor dem Start.
Hinweis
In einigen Fällen kann ein Gerät mit wenig Arbeitsspeicher keine Ereignisse senden.
Ist die App in der vorherigen Sitzung abgestürzt?
Nach dem Starten des SDK können Sie jederzeit überprüfen, ob die App beim vorherigen Start abgestürzt ist:
[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession
Dies ist nützlich, wenn Sie das Verhalten oder die Benutzeroberfläche Ihrer App nach einem Absturz anpassen möchten.
Hinweis
Diese Methode darf nur verwendet werden, nachdem MSACCrashes
sie gestartet wurde. Sie wird immer zurückgegeben NO
oder false
vor dem Start.
Details zum letzten Absturz
Wenn Ihre App zuvor abgestürzt ist, können Sie Details zum letzten Absturz abrufen.
MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport
Hinweis
Diese Methode darf nur verwendet werden, nachdem Crashes
gestartet wurde. Sie wird immer vor dem Start zurückgegeben nil
.
Es gibt zahlreiche Anwendungsfälle für diese API. Am häufigsten sind Benutzer, die diese API aufrufen und ihre benutzerdefinierten CrashesDelegate implementieren.
Anpassen der Nutzung von App Center-Abstürze
App Center-Abstürze bietet Rückrufe für Entwickler, um zusätzliche Aktionen vor und beim Senden von Absturzprotokollen an App Center auszuführen.
Um Ihr benutzerdefiniertes Verhalten hinzuzufügen, müssen Sie das CrashesDelegate
-Protokoll übernehmen. Alle zugehörigen Methoden sind optional.
Registrieren als Stellvertretung
[MSACCrashes setDelegate:self];
Crashes.delegate = self
Hinweis
Sie müssen den Delegaten festlegen , bevor Sie aufrufen AppCenter.start
, da App Center mit der Verarbeitung unmittelbar nach dem Start abstürzt.
Sollte der Absturz verarbeitet werden?
Implementieren Sie die crashes:shouldProcessErrorReport:
-methode in der Klasse, die das CrashesDelegate
-protocol verwendet, wenn Sie entscheiden möchten, ob ein bestimmter Absturz verarbeitet werden muss oder nicht. Es kann z. B. zu einem Absturz auf Systemebene kommen, den Sie ignorieren und den Sie nicht an App Center senden möchten.
- (BOOL)crashes:(MSACCrashes *)crashes shouldProcessErrorReport:(MSACErrorReport *)errorReport {
return YES; // return YES if the crash report should be processed, otherwise NO.
}
func crashes(_ crashes: Crashes, shouldProcess errorReport: ErrorReport) -> Bool {
return true; // return true if the crash report should be processed, otherwise false.
}
Behandelte Fehler
Mit App Center können Sie auch Fehler mithilfe von behandelten Ausnahmen über trackError
die -Methode nachverfolgen. Eine App kann optional Eigenschaften oder/und Anlagen an einen behandelten Fehlerbericht anfügen, um weiteren Kontext bereitzustellen.
@try {
// Throw error.
} @catch (NSError *error) {
// Init attachments.
NSArray<MSACErrorAttachmentLog *> attachments = @[ MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"] ]
// Init properties.
NSDictionary *properties = @{ "Category" : "Music", "Wifi" : "On" };
// Track errors.
[MSACCrashes trackError:error withProperties:properties attachments:attachments];
[MSACCrashes trackError:error withProperties:properties attachments:nil];
[MSACCrashes trackError:error withProperties:nil attachments:attachments];
[MSACCrashes trackError:error withProperties:nil attachments:nil];
}
do {
// Throw error.
} catch {
// Init attachments.
let attachments = [ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")]
// Init properties.
let properties:Dictionary<String, String> = ["Category" : "Music", "Wifi" : "On"]
// Track errors.
Crashes.trackError(error, properties: properties, attachments: attachments)
Crashes.trackError(error, properties: properties, attachments: nil)
Crashes.trackError(error, properties: nil, attachments: attachments)
Crashes.trackError(error, properties: nil, attachments: nil)
}
Für Nachverfolgungsausnahmen können Sie die -Methode verwenden trackException
:
@try {
// Throw exceptions.
} @catch (NSException *exception) {
// Init exceptions.
MSACExceptionModel *customException1 = [MSACExceptionModel initWithType:@"Custom exception" exceptionMessage:"Track custom exception.", stackTrace:exception.callStackSymbols];
MSACExceptionModel *customException2 = [MSACExceptionModel initWithException:exception];
// Track exceptions.
[MSACCrashes trackException:customException1 withProperties:properties attachments:nil];
[MSACCrashes trackException:customException2 withProperties:properties attachments:nil];
}
do {
// Throw exception.
} catch {
// Init exception.
let exception = ExceptionModel(withType: "Custom exception", exceptionMessage: "Track custom exception.", stackTrace: Thread.callStackSymbols)
// Track exception.
Crashes.trackException(exception, properties: properties, attachments: nil)
}
Anfordern der Zustimmung des Benutzers zum Senden eines Absturzprotokolls
Wenn Ihnen der Datenschutz des Benutzers wichtig ist, sollten Sie die Benutzerbestätigung erhalten, bevor Sie einen Absturzbericht an App Center senden. Das SDK macht einen Rückruf verfügbar, der App Center-Abstürze angibt, die Benutzerbestätigung abzuwarten, bevor Absturzberichte gesendet werden.
Wenn Sie sich dafür entschieden haben, sind Sie dafür verantwortlich, die Bestätigung des Benutzers zu erhalten, z. B. über eine Dialogaufforderung mit einer der folgenden Optionen: Immer senden, senden und Nicht senden. Basierend auf der Eingabe geben Sie App Center-Abstürze an, was zu tun ist, und der Absturz wird dann entsprechend behandelt.
Hinweis
Das SDK zeigt dafür kein Dialogfeld an. Die App muss eine eigene Benutzeroberfläche bereitstellen, um die Zustimmung des Benutzers zu verlangen.
Die folgende Methode zeigt, wie Sie einen Benutzerbestätigungshandler einrichten:
[MSACCrashes setUserConfirmationHandler:(^(NSArray<MSACErrorReport *> *errorReports) {
// Your code to present your UI to the user, e.g. an NSAlert.
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:@"Sorry about that!"];
[alert setInformativeText:@"Do you want to send an anonymous crash report so we can fix the issue?"];
[alert addButtonWithTitle:@"Always send"];
[alert addButtonWithTitle:@"Send"];
[alert addButtonWithTitle:@"Don't send"];
[alert setAlertStyle:NSWarningAlertStyle];
switch ([alert runModal]) {
case NSAlertFirstButtonReturn:
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
break;
case NSAlertSecondButtonReturn:
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
break;
case NSAlertThirdButtonReturn:
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
break;
default:
break;
}
return YES; // Return YES if the SDK should await user confirmation, otherwise NO.
})];
Crashes.setUserConfirmationHandler({ (errorReports: [ErrorReport]) in
// Your code to present your UI to the user, e.g. an NSAlert.
let alert: NSAlert = NSAlert()
alert.messageText = "Sorry about that!"
alert.informativeText = "Do you want to send an anonymous crash report so we can fix the issue?"
alert.addButton(withTitle: "Always send")
alert.addButton(withTitle: "Send")
alert.addButton(withTitle: "Don't send")
alert.alertStyle = NSWarningAlertStyle
switch (alert.runModal()) {
case NSAlertFirstButtonReturn:
Crashes.notify(with: .always)
break;
case NSAlertSecondButtonReturn:
Crashes.notify(with: .send)
break;
case NSAlertThirdButtonReturn:
Crashes.notify(with: .dontSend)
break;
default:
break;
}
return true // Return true if the SDK should await user confirmation, otherwise return false.
})
Falls Sie im obigen Handlerblock zurückkehren YES
/true
, sollte Ihre App die Benutzerberechtigung erhalten und dem SDK mithilfe der folgenden API eine Nachricht mit dem Ergebnis senden. Wenn Sie hierfür eine Warnung verwenden, wie im obigen Beispiel, würden Sie sie basierend auf dem Ergebnis (ModalResponse) des Aufrufs runModal
aufrufen.
// Depending on the user's choice, call notifyWithUserConfirmation: with the right value.
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
// Depending on the user's choice, call notify(with:) with the right value.
Crashes.notify(with: .dontSend)
Crashes.notify(with: .send)
Crashes.notify(with: .always)
Aktivieren des Abfangens von nicht abgefangenen Ausnahmen, die im Standard-Thread ausgelöst werden
AppKit fängt Ausnahmen ab, die im Standard Thread ausgelöst werden, wodurch verhindert wird, dass die Anwendung unter macOS abstürzt, sodass das SDK diese Abstürze nicht abfangen kann. Um das iOS-Verhalten zu imitieren, legen Sie das Flag vor der SDK-Initialisierung fest NSApplicationCrashOnExceptions
. Dieses Flag ermöglicht es der Anwendung, bei nicht abgefangenen Ausnahmen abzustürzen, und das SDK kann diese melden.
[[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions" : @YES }];
UserDefaults.standard.register(defaults: ["NSApplicationCrashOnExceptions": true])
Hinweis
Das App Center SDK legt das Flag in Den Versionen 1.10.0 und niedriger automatisch fest. Ab Version 1.11.0 wird dieses Flag nicht mehr automatisch festgelegt.
Deaktivieren der Weiterleitung der Methodenaufrufe der Anwendung Standard Klasse an App Center-Abstürze
Das App Center Crashes SDK verwendet swizzling, um die Integration zu verbessern, indem einige der Methodenaufrufe der Anwendung Standard Klasse selbst weitergeleitet werden. Methodenschwizzling ist eine Möglichkeit, die Implementierung von Methoden zur Laufzeit zu ändern. Wenn Sie swizzling aus irgendeinem Grund nicht verwenden möchten (z. B. aufgrund einer bestimmten Richtlinie), sollten Sie die Methoden der Anwendung reportException:
und sendEvent:
selbst überschreiben, damit Abstürze Ausnahmen, die im Standard Thread ausgelöst werden, ordnungsgemäß melden.
Erstellen Sie die Datei ReportExceptionApplication.m , und fügen Sie die folgende Implementierung hinzu:
@import Cocoa; @import AppCenterCrashes; @interface ReportExceptionApplication : NSApplication @end @implementation ReportExceptionApplication - (void)reportException:(NSException *)exception { [MSACCrashes applicationDidReportException:exception]; [super reportException:exception]; } - (void)sendEvent:(NSEvent *)theEvent { @try { [super sendEvent:theEvent]; } @catch (NSException *exception) { [self reportException:exception]; } } @end
Hinweis
Swift funktioniert
try
/catch
nicht mit .NSException
Diese Ausnahmen können nur in Objective-C behandelt werden.Öffnen Sie die Datei Info.plist , und ersetzen Sie in diesem Beispiel die NSApplication im Feld Prinzipalklasse durch den Namen Ihrer Anwendungsklasse, ReportExceptionApplication .
Um swizzling im App Center SDK zu deaktivieren, fügen Sie den
AppCenterApplicationForwarderEnabled
Schlüssel zur Datei Info.plist hinzu, und legen Sie den Wert auf fest0
.
Abrufen von Informationen zum sendenden status für ein Absturzprotokoll
Manchmal möchten Sie die status ihres App-Absturzes kennen. Ein häufiger Anwendungsfall ist, dass Sie möglicherweise eine Benutzeroberfläche anzeigen möchten, die den Benutzern mitteilt, dass Ihre App einen Absturzbericht übermittelt. Falls Ihre App nach dem Start schnell abstürzt, möchten Sie das Verhalten der App anpassen, um sicherzustellen, dass die Absturzprotokolle übermittelt werden können. Das CrashesDelegate
-protokoll definiert drei verschiedene Rückrufe, die Sie in Ihrer App verwenden können, um über die Vorgänge benachrichtigt zu werden:
Der folgende Rückruf wird aufgerufen, bevor das SDK ein Absturzprotokoll sendet.
- (void)crashes:(MSACCrashes *)crashes willSendErrorReport:(MSACErrorReport *)errorReport {
// Your code, e.g. to present a custom UI.
}
func crashes(_ crashes: Crashes, willSend errorReport: ErrorReport) {
// Your code, e.g. to present a custom UI.
}
Falls Netzwerkprobleme oder ein Ausfall des Endpunkts auftreten und Sie die App neu starten, willSendErrorReport
wird nach dem Prozessneustart erneut ausgelöst.
Der folgende Rückruf wird aufgerufen, nachdem das SDK erfolgreich ein Absturzprotokoll gesendet hat.
- (void)crashes:(MSACCrashes *)crashes didSucceedSendingErrorReport:(MSACErrorReport *)errorReport {
// Your code, e.g. to hide the custom UI.
}
func crashes(_ crashes: Crashes, didSucceedSending errorReport: ErrorReport) {
// Your code goes here.
}
Der folgende Rückruf wird aufgerufen, wenn das SDK ein Absturzprotokoll nicht senden konnte
- (void)crashes:(MSACCrashes *)crashes didFailSendingErrorReport:(MSACErrorReport *)errorReport withError:(NSError *)error {
// Your code goes here.
}
func crashes(_ crashes: Crashes, didFailSending errorReport: ErrorReport, withError error: Error) {
// Your code goes here.
}
didFailSendingErrorReport
Empfangen bedeutet, dass ein nicht wiederherstellbarer Fehler auftritt, z. B. ein 4xx-Code. Beispielsweise bedeutet 401 , dass falsch appSecret
ist.
Dieser Rückruf wird nicht ausgelöst, wenn es sich um ein Netzwerkproblem handelt. In diesem Fall versucht das SDK immer wieder (und hält auch Wiederholungen an, während die Netzwerkverbindung unterbrochen ist).
Hinzufügen von Anlagen zu einem Absturzbericht
Sie können Binär- und Textanlagen zu einem Absturzbericht hinzufügen. Das SDK sendet sie zusammen mit dem Absturz, sodass Sie sie im App Center-Portal sehen können. Der folgende Rückruf wird direkt vor dem Senden des gespeicherten Absturzes von früheren Anwendungsstarts aufgerufen. Es wird nicht aufgerufen, wenn der Absturz auftritt. Hier sehen Sie ein Beispiel für das Anfügen von Text und einem Bild an einen Absturz:
- (NSArray<MSACErrorAttachmentLog *> *)attachmentsWithCrashes:(MSACCrashes *)crashes
forErrorReport:(MSACErrorReport *)errorReport {
MSACErrorAttachmentLog *attachment1 = [MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"];
MSACErrorAttachmentLog *attachment2 = [MSACErrorAttachmentLog attachmentWithBinary:[@"Fake image" dataUsingEncoding:NSUTF8StringEncoding] filename:@"fake_image.jpeg" contentType:@"image/jpeg"];
return @[ attachment1, attachment2 ];
}
func attachments(with crashes: Crashes, for errorReport: ErrorReport) -> [ErrorAttachmentLog]? {
let attachment1 = ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")
let attachment2 = ErrorAttachmentLog.attachment(withBinary: "Fake image".data(using: String.Encoding.utf8), filename: nil, contentType: "image/jpeg")
return [attachment1!, attachment2!]
}
Hinweis
Das Größenlimit beträgt derzeit 7 MB. Der Versuch, eine größere Anlage zu senden, löst einen Fehler aus.
Aktivieren oder Deaktivieren von App Center-Abstürze zur Laufzeit
Sie können App Center-Abstürze zur Laufzeit aktivieren und deaktivieren. Wenn Sie es deaktivieren, wird vom SDK keine Absturzberichte für die App ausgeführt.
[MSACCrashes setEnabled:NO];
Crashes.enabled = false
Um App Center-Abstürze erneut zu aktivieren, verwenden Sie dieselbe API, übergeben YES
/true
sie aber als Parameter.
[MSACCrashes setEnabled:YES];
Crashes.enabled = true
Der Zustand wird im Speicher des Geräts bei allen Anwendungsstarts beibehalten.
Hinweis
Diese Methode darf erst nach dem Crashes
Start verwendet werden.
Überprüfen, ob App Center-Abstürze aktiviert ist
Sie können auch überprüfen, ob App Center-Abstürze aktiviert ist oder nicht:
BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled
Hinweis
Diese Methode darf erst nach dem Crashes
Start verwendet werden. Sie wird immer vor dem Start zurückgegeben false
.
Deaktivieren der Mach-Ausnahmebehandlung
App Center Crashes verwendet standardmäßig den Mach-Ausnahmehandler, um schwerwiegende Signale, z. B. Stapelüberläufe, über einen Mach-Ausnahmeserver abzufangen.
Die disableMachExceptionHandler
-Methode bietet eine Option zum Deaktivieren des Abfangens schwerwiegender Signale über einen Mach-Ausnahmeserver. Wenn Sie den Mach-Ausnahmehandler deaktivieren möchten, sollten Sie diese Methode aufrufen, BEVOR Sie das SDK starten. Ihr typischer Setupcode würde wie folgt aussehen:
[MSACCrashes disableMachExceptionHandler];
[MSACAppCenter start:@"{Your App Secret}" withServices:@[[MSACAnalytics class], [MSACCrashes class]]];
Crashes.disableMachExceptionHandler()
AppCenter.start(withAppSecret: "{Your App Secret}", services: [Analytics.self, Crashes.self])