共用方式為


App Center 損毀 (macOS)

這很重要

Visual Studio App Center 於 2025 年 3 月 31 日淘汰,但分析和診斷功能除外,這些功能將持續支援到 2026 年 6 月 30 日。 瞭解更多資訊。

App Center 崩潰會在每次應用程式當機時自動產生當機記錄檔。 記錄會先寫入裝置的記憶體,當使用者再次啟動應用程式時,當機報告會傳送至 App Center。 收集崩潰資訊適用於 Beta 和上線的應用程式,也就是已提交到 App Store 的應用程式。 當機記錄包含協助您修正當機的重要資訊。

如果您尚未在應用程式中設定 SDK,請遵循 開始使用 一節。

此外,macOS 上的當機記錄需要符號,請參閱 App Center 診斷檔 ,說明如何為您的應用程式提供符號。

備註

4.0.0 App Center 重大變更版本中引進。 遵循 移轉至 App Center SDK 4.0.0 和更新 版本一節,從舊版移轉 App Center。

擴充功能中的當機報告

App Center 支援 macOS 擴充功能中的當機報告。 使用方式與容器應用程式中相同。

產生測試當機

App Center 當機提供 API 來產生測試當機,以便輕鬆測試 SDK。 此 API 只能用於測試/Beta 應用程式,且不會在生產應用程式中執行任何動作。

[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()

取得先前當機的詳細資訊

App Center Crashes 有兩個 API,可以在應用程式當機時提供更多資訊。

應用程式在上一個會話中是否收到記憶體不足的警告?

在啟動 SDK 之後,您可以隨時檢查應用程式是否在上一個工作階段中收到記憶體警告:

[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession

備註

此方法只能在 Crashes 啟動後使用,在啟動之前,它總是會回傳 NOfalse

備註

在某些情況下,記憶體不足的裝置無法傳送事件。

應用程式在上一個工作階段中是否當機?

在啟動 SDK 之後,您可以隨時檢查應用程式是否在上一次啟動中當機:

[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession

如果您想要在發生當機后調整應用程式的行為或 UI,這會派上用場。

備註

此方法只能在 MSACCrashes 啟動後使用,在啟動之前,它總是會回傳 NOfalse

上次當機的詳細數據

如果您的應用程式先前當機,您可以取得上次當機的詳細數據。

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

備註

這個方法只能在 Crashes 已啟動後使用,開始之前它總是會傳回 nil

此 API 有許多使用案例,最常見的使用案例是呼叫此 API 並實作其自定義 CrashesDelegate 的人員。

自訂 App Center 當機的使用方式

App Center 當機提供回呼,讓開發人員在將損毀記錄傳送至 App Center 之前和時執行其他動作。

若要新增自定義行為,您必須採用 CrashesDelegate-protocol,其所有方法都是選擇性的。

註冊為代表

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

備註

您必須在呼叫 之前設定 AppCenter.start,因為 App Center 會在啟動後立即開始處理錯誤。

是否應該處理當機?

在採用 crashes:shouldProcessErrorReport: 協定的類別中實作 CrashesDelegate 方法,如果您想要決定是否需要處理特定當機。 例如,您可能會想要忽略系統層級的崩潰,而且您也不希望將其傳送至 App Center。

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

已處理的錯誤

App Center 也可讓您透過 trackError 方法使用已處理的例外狀況來追蹤錯誤。 應用程式可以選擇性地將屬性或/和附件附加至已處理的錯誤報告,以提供進一步的內容。

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

針對追蹤例外狀況,您可以使用 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)
}

如果用戶隱私權對於您很重要,您可能會想要先取得使用者確認,再將當機報告傳送至 App Center。 SDK 會公開回呼,告知 App Center 損毀在傳送任何損毀報告之前等候用戶確認。

如果您選擇這樣做,您必須負責取得使用者的確認,例如透過具有下列其中一個選項的對話框提示: 永遠傳送傳送不要傳送。 根據輸入,您將告訴 App Center 崩潰需執行的動作,然後會據以處理崩潰。

備註

SDK 不會顯示此對話框,應用程式必須提供自己的 UI 以要求使用者同意。

下列方法示範如何設定使用者確認處理程式:

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

如果您在上述處理程式區塊中傳回 YES/true ,您的應用程式應該會使用下列 API 取得使用者許可權並訊息 SDK 與結果。 如果您使用此警告,如上述範例所示,您會根據呼叫的結果(runModal)呼叫它。

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

啟用在主線程上捕捉未攔截的例外狀況拋出

AppKit 會捕捉在主線程上拋出的例外狀況,防止應用程式在 macOS 上崩潰,因此 SDK 無法捕捉這些崩潰。 若要模擬 iOS 行為,請在 SDK 初始化之前設定 NSApplicationCrashOnExceptions 旗標,此旗標可讓應用程式在未攔截的例外狀況上當機,且 SDK 可以報告它們。

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

備註

App Center SDK 會在 1.10.0 版和以下版本中自動設定旗標。 從 1.11.0 版開始,此旗標將不再自動設定。

停用應用程式主要類別方法呼叫至 App Center 損毀的轉送

App Center 損毀 SDK 會使用令人眼花繚亂的方式,藉由轉送應用程式主要類別的一些方法呼叫來改善其整合。 方法交換是在執行期間改變方法實作的一種技術。 如果您基於任何理由不想使用方法交換(例如,因為特定原則),您應該自行覆寫應用程式的 reportException:sendEvent: 方法,以便 Crashes 正確報告在主線程上擲出的例外狀況。

  1. 建立 ReportExceptionApplication.m 檔案,並新增下列實作:

    @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
    

    備註

    try / catch無法使用NSException搭配Swift。 這些例外狀況只能在 Objective-C 中處理。

  2. 開啟 Info.plist 檔案,並將 Principal 類別欄位中的 NSApplication 取代為您的應用程式類別名稱 ReportExceptionApplication 在此範例中。

  3. 若要停用 App Center SDK 中的切換,請將金鑰新增 AppCenterApplicationForwarderEnabledInfo.plist 檔案,並將值設定為 0

取得當機記錄檔傳送狀態的相關資訊

有時,您想要知道應用程式當機狀態。 常見的使用案例是,您可能會想要顯示UI,告知使用者您的應用程式正在提交當機報告,或者,如果app在啟動後快速當機,您想要調整應用程式的行為,以確保可以提交當機記錄。 CrashesDelegate-protocol 會定義三個不同的回呼,您可以在應用程式中用來收到發生狀況的通知:

SDK 傳送當機記錄檔之前,將會調用下列回呼函式

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

如果我們在端點上有網路問題或中斷,而且您重新啟動應用程式, willSendErrorReport 則會在進程重新啟動后再次觸發。

在 SDK 成功傳送當機記錄檔後,將會執行下列回呼函數

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

如果 SDK 無法傳送當機記錄檔,將會叫用下列回呼

- (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接收表示發生無法復原的錯誤,例如發生 4xx 碼。 例如, 401 表示 appSecret 錯誤。

若是網路問題,則不會觸發此回呼。 在此情況下,SDK 會持續重試(並在網路連線關閉時暫停重試)。

將附件新增至當機報表

您可以將二進位和文字附件新增至當機報表。 SDK 會連同當機一起傳送它們,讓您可以在 App Center 入口網站中看到它們。 在傳送先前應用程式啟動時生成的預存當機報告之前,會立即調用以下的回呼函數。 當系統崩潰時,不會被調用。 以下是將文字和圖片附加至故障報告的範例:

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

備註

大小限制目前為 7 MB。 嘗試傳送較大的附件將會觸發錯誤。

在運行時間啟用或停用 App Center 當機

您可以在執行時間啟用和停用 App Center 崩潰功能。 如果您將其停用,SDK 將不會針對應用程式執行任何當機報告。

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

若要再次啟用App Center當機,請使用相同的API,但傳遞 YES/true 做為參數。

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

狀態會保存在裝置跨應用程式啟動時的記憶體中。

備註

只在啟動 Crashes 之後,才能使用這個方法。

檢查應用程式中心崩潰是否已啟用

您也可以檢查 App Center 損毀是否已啟用:

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

備註

這個方法只能在 Crashes 已啟動後使用,開始之前它總是會傳回 false

停用Mach例外狀況處理

根據預設,App Center 崩潰會使用 Mach 例外狀況處理程式,透過 Mach 例外狀況伺服器捕捉致命訊號,如堆疊溢出。

disableMachExceptionHandler-method 提供一個選項,可通過Mach異常服務器停用攔截致命信號。 如果您想要停用 Mach 例外狀況處理程式,您應該先呼叫此方法, 啟動 SDK。 您的一般設定程式代碼看起來會像這樣:

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