Delen via


App Center loopt vast (macOS)

Belangrijk

Visual Studio App Center is op 31 maart 2025 buiten gebruik gesteld, met uitzondering van de functies analyse en diagnose, die tot 30 juni 2026 nog steeds worden ondersteund. Meer informatie.

App Center-crashes genereren automatisch een crashlogboek telkens wanneer uw app vastloopt. Het logboek wordt eerst naar de opslag van het apparaat geschreven en wanneer de gebruiker de app opnieuw start, wordt het crashrapport verzonden naar App Center. Het verzamelen van crashes werkt voor zowel bèta- als live-apps, bijvoorbeeld voor de apps die zijn verzonden naar de App Store. Crashlogboeken bevatten waardevolle informatie voor u om de crash op te lossen.

Volg de sectie Aan de slag als u de SDK nog niet hebt ingesteld in uw toepassing.

Ook crashlogboeken op macOS vereisen symbolicatie, raadpleeg de App Center Diagnostics-documentatie waarin wordt uitgelegd hoe u symbolen voor uw app kunt opgeven.

Opmerking

In de 4.0.0 versie van App Center zijn belangrijke wijzigingen geïntroduceerd. Volg de sectie Migreren naar App Center SDK 4.0.0 en hoger om App Center te migreren vanuit eerdere versies.

Crashrapporteren in extensies

App Center ondersteunt crashrapportage in macOS-extensies. Het gebruik is hetzelfde als in de containertoepassing.

Een testcrash genereren

App Center-crashes biedt u een API om een testcrash te genereren voor eenvoudige tests van de SDK. Deze API kan alleen worden gebruikt in test-/bèta-apps en doet niets in productie-apps.

[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()

Meer informatie over een eerdere crash

App Center Crashes heeft twee API's die u meer informatie geven voor het geval uw app is vastgelopen.

Heeft de app een waarschuwing met weinig geheugen ontvangen in de vorige sessie?

U kunt op elk gewenst moment na het starten van de SDK controleren of de app een geheugenwaarschuwing heeft ontvangen in de vorige sessie:

[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession

Opmerking

Deze methode mag alleen worden gebruikt nadat Crashes deze is gestart. Deze retourneert altijd NO of false vóór de start.

Opmerking

In sommige gevallen kan een apparaat met weinig geheugen geen gebeurtenissen verzenden.

Is de app in de vorige sessie vastgelopen?

U kunt op elk gewenst moment na het starten van de SDK controleren of de app is vastgelopen tijdens de vorige start:

[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession

Dit is handig als u het gedrag of de gebruikersinterface van uw app wilt aanpassen nadat er een crash is opgetreden.

Opmerking

Deze methode mag alleen worden gebruikt nadat MSACCrashes deze is gestart. Deze retourneert altijd NO of false vóór de start.

Details over de laatste crash

Als uw app eerder is gecrasht, kunt u meer informatie krijgen over de laatste crash.

MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport

Opmerking

Deze methode mag alleen worden gebruikt nadat Crashes is gestart. Het zal altijd nil retourneren voordat het gestart is.

Er zijn talloze toepassingsgevallen voor deze API. Het meest voorkomende is dat mensen deze API aanroepen en hun aangepaste CrashesDelegate implementeren.

Pas de manier waarop u App Center Crashes gebruikt aan

App Center Crashes biedt callbacks voor ontwikkelaars om extra acties uit te voeren voordat en tijdens het verzenden van crashlogboeken naar App Center.

Als u uw aangepaste gedrag wilt toevoegen, moet u het CrashesDelegate-protocol gebruiken. Alle methoden zijn optioneel.

Registreren als gemachtigde

[MSACCrashes setDelegate:self];
Crashes.delegate = self

Opmerking

u moet de gemachtigde instellen voordat u de methode AppCenter.start aanroept, omdat App Center begint met het afhandelen van crashes direct na het starten.

Moet de crash worden verwerkt?

Implementeer de crashes:shouldProcessErrorReport:methode -in de klasse die het CrashesDelegate-protocol gebruikt als u wilt bepalen of een bepaalde crash moet worden verwerkt of niet. Er kan bijvoorbeeld een crash op systeemniveau zijn die u wilt negeren en dat u niet naar App Center wilt verzenden.

- (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.
}

Afgehandelde fouten

Met App Center kunt u ook fouten bijhouden met behulp van afgehandelde uitzonderingen via trackError de methode. Een app kan desgewenst eigenschappen of/en bijlagen toevoegen aan een afgehandeld foutenrapport om verdere context te bieden.

@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)
}

Voor uitzonderingen bijhouden kunt u de methode gebruiken 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)
}

Als gebruikersprivacy belangrijk voor u is, wilt u mogelijk bevestiging van de gebruiker krijgen voordat u een crashrapport naar App Center verzendt. De SDK biedt een callback die App Center Crashes instrueert om te wachten op bevestiging van de gebruiker voordat crashrapporten worden verzonden.

Als u hiervoor kiest, bent u verantwoordelijk voor het verkrijgen van de bevestiging van de gebruiker, bijvoorbeeld via een dialoogvensterprompt met een van de volgende opties: Altijd verzenden, verzenden en niet verzenden. Op basis van de invoer geeft u App Center Crashes instructies over wat te doen en wordt de crash vervolgens dienovereenkomstig afgehandeld.

Opmerking

In de SDK wordt hiervoor geen dialoogvenster weergegeven. De app moet een eigen gebruikersinterface opgeven om toestemming van de gebruiker te vragen.

De volgende methode laat zien hoe u een bevestigingshandler voor gebruikers instelt:

[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.
})

Als u terugkeert YES/true in het bovenstaande handlerblok, moet uw app gebruikersmachtigingen verkrijgen en de SDK met het resultaat bericht sturen met behulp van de volgende API. Als u hiervoor een waarschuwing gebruikt, zoals we in het bovenstaande voorbeeld doen, roept u deze aan op basis van het resultaat (ModalResponse) van runModal de oproep.

// 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)

Het mogelijk maken om niet-onderschepte uitzonderingen op de hoofdthread op te vangen

AppKit onderschept uitzonderingen die op de hoofdthread zijn gegooid, waardoor de toepassing niet vastloopt op macOS, zodat de SDK deze crashes niet kan opvangen. Als u het iOS-gedrag wilt nabootsen, stelt u de vlag NSApplicationCrashOnExceptions in vóór de SDK-initialisatie. Deze vlag laat de toepassing vastlopen bij niet-afgevangen uitzonderingen, waarna de SDK deze kan rapporteren.

[[NSUserDefaults standardUserDefaults] registerDefaults:@{ @"NSApplicationCrashOnExceptions" : @YES }];
UserDefaults.standard.register(defaults: ["NSApplicationCrashOnExceptions": true])

Opmerking

App Center SDK stelt de vlag automatisch in versie 1.10.0 en lager in. Vanaf versie 1.11.0 wordt deze vlag niet meer automatisch ingesteld.

Uitschakelen van het doorsturen van methode-aanroepen van de hoofdklasse van de toepassing naar App Center Crashes.

De App Center Crashes SDK maakt gebruik van swizzling om de integratie te verbeteren door een aantal van de methoden aanroepen van de hoofdklasse van de toepassing door te sturen. Methode swizzling is een manier om de implementatie van methoden tijdens runtime te wijzigen. Als u om welke reden dan ook geen swizzling wilt gebruiken (bijvoorbeeld vanwege een specifiek beleid), moet u zelf de reportException:- en sendEvent:-methoden van de applicatie overschrijven, zodat 'Crashes' de op de hoofdthread gegooide uitzonderingen correct kan rapporteren.

  1. Maak het bestand ReportExceptionApplication.m en voeg de volgende implementatie toe:

    @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
    

    Opmerking

    try / catchSwift werkt niet met NSException. Deze uitzonderingen kunnen alleen in Objective-C worden verwerkt.

  2. Open het bestand Info.plist en vervang de NSApplication in het veld Principal-klasse door de naam van uw toepassingsklasse, ReportExceptionApplication in dit voorbeeld.

  3. Als u swizzling in App Center SDK wilt uitschakelen, voegt u de sleutel toe aan het AppCenterApplicationForwarderEnabledbestand Info.plist en stelt u de waarde in op 0.

Informatie ophalen over de verzendstatus voor een crashlogboek

Soms wilt u weten wat de status van de crash van uw app is. Een veelvoorkomend gebruiksvoorbeeld is dat u de gebruikersinterface wilt weergeven die de gebruikers vertelt dat uw app een crashrapport indient, of, als uw app snel vastloopt na de start, wilt u het gedrag van de app aanpassen om ervoor te zorgen dat de crashlogboeken kunnen worden verzonden. Het CrashesDelegate-protocol definieert drie verschillende callbacks die u in uw app kunt gebruiken om op de hoogte te worden gesteld van wat er gebeurt:

De volgende callback wordt aangeroepen voordat de SDK een crashlogboek verzendt

- (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.
}

Als er netwerkproblemen of een storing op het eindpunt zijn en u de app opnieuw start, willSendErrorReport wordt deze opnieuw geactiveerd nadat het proces opnieuw is opgestart.

De volgende callback wordt aangeroepen nadat de SDK succesvol een crashrapport heeft verzonden.

- (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.
}

De volgende callback wordt aangeroepen als de SDK een crashlogboek niet kan verzenden

- (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.
}

Het ontvangen didFailSendingErrorReport betekent dat er een niet-herstelbare fout is opgetreden, zoals een 4xx-code . 401 betekent bijvoorbeeld dat het appSecret verkeerd is.

Deze callback wordt niet geactiveerd als het een netwerkprobleem is. In dit geval blijft de SDK pogingen herhalen (en worden die pogingen ook gepauzeerd terwijl de netwerkverbinding verstoord is).

Bijlagen toevoegen aan een crashrapport

U kunt binaire en tekstbijlagen toevoegen aan een crashrapport. De SDK verzendt ze samen met de crash, zodat u ze kunt zien in de App Center-portal. De volgende callback wordt aangeroepen vlak voordat de opgeslagen crash van eerdere applicatiestarts wordt verstuurd. Deze wordt niet aangeroepen wanneer de crash plaatsvindt. Hier volgt een voorbeeld van het koppelen van tekst en een afbeelding aan een crash:

- (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!]
}

Opmerking

De groottelimiet is momenteel 7 MB. Als u probeert een grotere bijlage te verzenden, zal er een fout optreden.

De App Center-functie voor crashes tijdens uitvoering in- of uitschakelen

U kunt App Center-crashes tijdens de uitvoering van de applicatie in- en uitschakelen. Als u deze optie uitschakelt, zal de SDK geen crashrapportage uitvoeren voor de app.

[MSACCrashes setEnabled:NO];
Crashes.enabled = false

Als u App Center-crashes opnieuw wilt inschakelen, gebruikt u dezelfde API, maar geeft u YES/true deze door als een parameter.

[MSACCrashes setEnabled:YES];
Crashes.enabled = true

De status blijft behouden in de opslag van het apparaat tijdens het starten van de toepassing.

Opmerking

Deze methode mag alleen worden gebruikt nadat Crashes is gestart.

Controleren of App Center Crashes is ingeschakeld

U kunt ook controleren of App Center-crashes is ingeschakeld of niet:

BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled

Opmerking

Deze methode mag alleen worden gebruikt nadat Crashes is gestart. Het zal altijd false retourneren voordat het gestart is.

Afhandeling van Mach-uitzonderingen uitschakelen

App Center Crashes maakt standaard gebruik van de Mach-uitzonderingshandler om fatale signalen te vangen, bijvoorbeeld stack-overloop, via een Mach-uitzonderingsserver.

De disableMachExceptionHandlermethode -biedt een optie om het vangen van fatale signalen via een Mach-uitzonderingsserver uit te schakelen. Als u de Mach-uitzonderingshandler wilt uitschakelen, moet u deze methode aanroepen VOORDAT u de SDK start. Uw typische installatiecode ziet er als volgt uit:

[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])