windows核心程式設計---錯誤報告與應用程式恢復

raindayinrain發表於2017-12-24

-windows錯誤報告控制檯
一個程式因為未處理異常而終止時,WER會建立關於未處理異常及其執行上下文的錯誤報告。

如得到使用者許可,報告會通過安全通道發給microsoft伺服器,在那裡它和資料庫已知問題比較,如有解決方案,伺服器將它發給使用者。

使用者不傳送報告給microsoft伺服器,生成的報告會儲存在使用者機器上,通過WER控制檯,使用者可在本地機器上瀏覽檢視報告。

Program Reports andSolutions–>View problem history。
WER生成的4個檔案的詳細資訊。
AppCompat.txt 失敗程式匯入的模組列表
Memory.hdmp 失敗程式的使用者模式轉儲,包含,棧,堆,控制程式碼表格。
MiniDump.mdmp 失敗程式使用者模式小型轉儲。
Version.txt 當前安裝版本

-可程式設計windows錯誤報告

HRESULT WerSetFlags(DWORD dwFlags);

HRESULT WerGetFlags(HANDLE hProcess, PDWORD pdwFlags);

// 禁用報告生成與傳送
HRESULT WerAddExcludedApplication(PCWSTR pwzExeName, BOOL bAllUsers);
// 啟用錯誤報告生成和傳送
HRESULT WerRemoveExcludedApplication(PCWSTR pwzExeName, BOOL bAllUsers);

WER_FAULT_REPORTING_*xx
xx:
FLAG_NOHEAP=1 生成的報告不含堆資訊
FLAG_DISABLE_THREAD_SUSPENSION=4
FLAG_QUEUE=2
FLAG_QUEUE_UPLOAD=8

-對程式中所有的問題報告進行定製
可能需定製錯誤報告情況:
在編寫自己的未處理異常過濾程式
在未處理異常沒發生下也生成報告
往錯誤報告新增更多資訊

// 新增任意資料塊
// 呼叫此函式後,問題發生時,範圍內的位元組會存在小型轉儲中,
// 可用事後偵錯程式檢視這些位元組。
// 可多次用WerRegisterMemoryBlock將多個資料塊存在小型轉儲中
HRESULT WerRegisterMemoryBlock(
// 記憶體地址
PVOID pvAddress,
// 尺寸
DWORD dwSize
);

// 每當一個問題報告生成,下面的函式註冊的檔案都會儲存在報告裡。
// 新增任意檔案到問題報告
HRESULT WerRegisterFile(
// 目標檔案的路徑名
PCWSTR pwzFilename,
// WerRegFileTypeUserDocument 文件檔案
// WerRegFileTypeOther
WER_REGISTER_FILE_TYPE regFileType,
// WER_FILE_xx
// xx:
// DELETE_WHEN_DONE 提交報告後就刪除檔案
// ANONYMOUS_DATA
DWORD dwFlags
);

// 移除
HRESULT WerUnregisterMemoryBlock(PVOID pvAddress);
HRESULT WerUnregisterFile(PCWSTR pwzFilePath);

-問題報告的建立與定製
HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting\

MaxArchiveCount 存檔中檔案數目上限
MaxQueueCount 發給Microsoft伺服器前儲存在本地機器佇列裡的報告數目上限。

// 問題報告的建立,定製,提交給WER按以下步驟呼叫不同函式實現:
1.WerReportCreate建立新報告

typedef struct _WER_REPORT_INFORMATION {
  DWORD  dwSize;
  HANDLE hProcess;
  WCHAR  wzConsentKey[64];
  WCHAR  wzFriendlyEventName[128];
  WCHAR  wzApplicationName[128];
  WCHAR  wzApplicationPath[MAX_PATH];
  WCHAR  wzDescription[512];
  HWND   hwndParent;
} WER_REPORT_INFORMATION, *PWER_REPORT_INFORMATION;



HRESULT WerReportCreate(
// 作為問題簽名第一個元素的Unicode字串
PCWSTR pwzEventType,
// WerReportNonCritical 將報告放入佇列,依據同意設定上傳Microsoft伺服器
// WerReportCritical 將報告放入本地佇列
// WerReportApplicationCrash 
// WerReportApplicationHang 
WER_REPORT_TYPE repType,
// 
PWER_REPORT_INFORMATION pReportInformation,
// 執行成功時,返回報告控制程式碼
HREPORT* phReport
);

2.WerReportSetParameter零次或多次設定報告

HRESULT WINAPI WerReportSetParameter(
// 報告控制程式碼
  _In_     HREPORT hReportHandle,
  // 鍵值對
  // WER_P0---WER_P9
  // 如傳入的dwparamID不在WER_P0---WER_P9,失敗,返回:E_INVALIDARG。如設定WER_PX,則WER_P0---WER_P(X-1)也要設定
  _In_     DWORD   dwparamID,
  _In_opt_ PCWSTR  pwzName,
  _In_     PCWSTR  pwzValue
);

對非定製報告,WER的預設引數:
1 程式名
2 程式版本
3 標明程式二進位制檔案構建的時間戳
4 失敗模組名稱
5 失敗模組版本
6 標明程式二進位制檔案構建的時間戳
7 異常程式碼,記載剛發生異常型別
8 發生錯誤地方相對模組起始位置偏移量

3.WerReportAddDump將小型轉儲放進報告

HRESULT WINAPI WerReportAddDump(
  _In_     HREPORT                    hReportHandle,
 // 控制程式碼須具備:
 // STANDARD_RIGHTS_READ
 // PROCESS_QUERY_INFORMATION
 // 許可權
  _In_     HANDLE                     hProcess,
  _In_opt_ HANDLE                     hThread,
  // 轉儲文件型別相關
  _In_     WER_DUMP_TYPE              dumpType,
  // 額外異常資訊
  _In_opt_ PWER_EXCEPTION_INFORMATION pExceptionParam,
  // 轉儲文件型別相關
  _In_opt_ PWER_DUMP_CUSTOM_OPTIONS   pDumpCustomOptions,
  // 0
  // WER_DUMP_NOHEAP_ONQUEUE
  _In_     DWORD                      dwFlags
);

4.WerReportAddFile零次或多次將任意檔案放進報告

HRESULT WINAPI WerReportAddFile(
  _In_ HREPORT       hReportHandle,
  _In_ PCWSTR        pwzPath,
  // WerFileTypeMicrodump
  // WerFileTypeMinidump
  // WerFileTypeHeapdump
  // WerFileTypeUserDocument
  // WerFileTypeOther
  _In_ WER_FILE_TYPE repFileType,
  _In_ DWORD         dwFileFlags
);

5.WerReportSetUIOption修改一些字串

HRESULT WINAPI WerReportSetUIOption(
  _In_ HREPORT       hReportHandle,
  _In_ WER_REPORT_UI repUITypeID,
  _In_ PCWSTR        pwzValue
);

6.WerReportSubmit提交報告。

HRESULT WINAPI WerReportSubmit(
  _In_      HREPORT            hReportHandle,
  // WerConsentNotAsked
  // WerConsentApproved
  // WerConsentDenied
  _In_      WER_CONSENT        consent,
  // HONOR_RECOVERY 
  // HONOR_RESTART
  // SHOW_DEBUG
  // NO_CLOSE_UI
  // START_MINIMIZED
  // QUEUE
  // NO_QUEUE
  // NO_ARCHIVE
  // OUTOFPROCESS
  // OUTOFPROCESS_ASYNC
  // ADD_REGISTERED_DATA
  _In_      DWORD              dwFlags,
  // 
  _Out_opt_ PWER_SUBMIT_RESULT pSubmitResult
);

7.WerReportCloseHandle關閉報告

HRESULT WINAPI WerReportCloseHandle(
  _In_ HREPORT hReportHandle
);

-應用的自動重啟與恢復
WER允許應用終止後自動重啟。

// 在WER中註冊自己
HRESULT RegisterApplicationRestart(
PCWSTR pwzCommandline,
// RESTART_NO_CRASH 崩潰下不重啟
// RESTART_NO_HANG 掛起下不重啟
// RESTART_NO_PATCH 安裝更新後不重啟
// RESTART_NO_REBOOT 
DWORD dwFlags
);

HRESULT UnregisterApplicationRestart();

-對應用恢復支援

HRESULT RegisterApplicationRecoveryCallback(
APPLICATION_RECOVERY_CALLBACK pfnRecoveryCallback,
PVOID pvParameter,
DWORD dwPingInterval,
DWORD dwFlags
);


// APPLICATION_RECOVERY_CALLBACK
DWORD WINAPI ApplicationRecoveryCallback(PVOID pvParameter);

// 示例:
DWORD WINAPI ApplicationRecoveryCallback(PVOID pvParameter)
{
DWORD dwReturn = 0;
BOOL bCancelled = FALSE;
while(!bCancelled)
{
ApplicationRecoveryInProgress(&bCancelled);

if(bCancelled)
{
...
ApplicationRecoveryFinished(FALSE);
}
else
{
if(MoreInformationToSave(())
{
///
}
else
{
ApplicationRecoveryFinished(TRUE);
bCancel = TRUE;
}
}
}

return dwReturn;
}

相關文章