/** * Set the ten Windows Error Reporting parameters * * Parameters 0 through 7 are predefined for Windows * Parameters 8 and 9 are user defined */ static void SetReportParameters( HREPORT ReportHandle, EXCEPTION_POINTERS* ExceptionInfo ) { HRESULT Result; TCHAR StringBuffer[1024] = { 0 }; TCHAR ModuleName[1024] = { 0 }; // Set the parameters for the standard problem signature HMODULE ModuleHandle = GetModuleHandle( NULL ); StringCchPrintf( StringBuffer, 1024, TEXT( "UE4-%s" ), FApp::GetGameName() ); Result = WerReportSetParameter( ReportHandle, WER_P0, TEXT( "Application Name" ), StringBuffer ); GetModuleFileName( ModuleHandle, ModuleName, 1024 ); PathStripPath( ModuleName ); GetModuleVersion( ModuleName, StringBuffer, 1024 ); Result = WerReportSetParameter( ReportHandle, WER_P1, TEXT( "Application Version" ), StringBuffer ); StringCchPrintf( StringBuffer, 1024, TEXT( "%08x" ), GetTimestampForLoadedLibrary( ModuleHandle ) ); Result = WerReportSetParameter( ReportHandle, WER_P2, TEXT( "Application Timestamp" ), StringBuffer ); HMODULE FaultModuleHandle = NULL; GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, ( LPCTSTR )ExceptionInfo->ExceptionRecord->ExceptionAddress, &FaultModuleHandle ); GetModuleFileName( FaultModuleHandle, ModuleName, 1024 ); PathStripPath( ModuleName ); Result = WerReportSetParameter( ReportHandle, WER_P3, TEXT( "Fault Module Name" ), ModuleName ); GetModuleVersion( ModuleName, StringBuffer, 1024 ); Result = WerReportSetParameter( ReportHandle, WER_P4, TEXT( "Fault Module Version" ), StringBuffer ); StringCchPrintf( StringBuffer, 1024, TEXT( "%08x" ), GetTimestampForLoadedLibrary( FaultModuleHandle ) ); Result = WerReportSetParameter( ReportHandle, WER_P5, TEXT( "Fault Module Timestamp" ), StringBuffer ); StringCchPrintf( StringBuffer, 1024, TEXT( "%08x" ), ExceptionInfo->ExceptionRecord->ExceptionCode ); Result = WerReportSetParameter( ReportHandle, WER_P6, TEXT( "Exception Code" ), StringBuffer ); INT_PTR ExceptionOffset = ( char* )( ExceptionInfo->ExceptionRecord->ExceptionAddress ) - ( char* )FaultModuleHandle; StringCchPrintf( StringBuffer, 1024, TEXT( "%p" ), ExceptionOffset ); Result = WerReportSetParameter( ReportHandle, WER_P7, TEXT( "Exception Offset" ), StringBuffer ); StringCchPrintf( StringBuffer, 1024, TEXT( "!%s!" ), FCommandLine::Get() ); Result = WerReportSetParameter( ReportHandle, WER_P8, TEXT( "Commandline" ), StringBuffer ); StringCchPrintf( StringBuffer, 1024, TEXT( "%s!%s!%s!%d" ), TEXT( BRANCH_NAME ), FPlatformProcess::BaseDir(), GetEngineMode(), BUILT_FROM_CHANGELIST ); Result = WerReportSetParameter( ReportHandle, WER_P9, TEXT( "BranchBaseDir" ), StringBuffer ); }
int wmain ( int argc, const wchar_t* argv[], const wchar_t* envp[] ) { HRESULT hr = E_FAIL; HREPORT ReportHandle = NULL; WER_REPORT_INFORMATION ReportInformation = {0}; WER_SUBMIT_RESULT SubmitResult; UNREFERENCED_PARAMETER (argv); UNREFERENCED_PARAMETER (argc); UNREFERENCED_PARAMETER (envp); wprintf (L"WerReportAddFile API Sample\n"); wprintf (L"---------------------------\n"); // // Report creation // // // First, populate the WER_REPORT_INFORMATION structure. // ReportInformation.dwSize = sizeof(WER_REPORT_INFORMATION); // // To report on the current process, set the hProcess field to NULL. // ReportInformation.hProcess = NULL; // // Set the Consent Key, i.e. the name used to look up consent settings // hr = StringCchCopy (ReportInformation.wzConsentKey, ARRAYSIZE(ReportInformation.wzConsentKey), L"Sample Consent Key"); if (FAILED(hr)) { wprintf (L"Failed to set the consent key, error: 0x%08X\n", hr); goto End; } // // Set the name of the application we are reporting on. // hr = StringCchCopy (ReportInformation.wzApplicationName, ARRAYSIZE(ReportInformation.wzApplicationName), L"UI Customization Sample"); if (FAILED(hr)) { wprintf (L"Failed to set the application name, error: 0x%08X\n", hr); goto End; } // // Set the application path. // hr = StringCchCopy (ReportInformation.wzApplicationPath, ARRAYSIZE(ReportInformation.wzApplicationPath), L"Sample Application Path"); if (FAILED(hr)) { wprintf (L"Failed to set the application path, error: 0x%08X\n", hr); goto End; } // // Set a description of the problem. // hr = StringCchCopy (ReportInformation.wzDescription, ARRAYSIZE(ReportInformation.wzDescription), L"Sample Problem Description"); if (FAILED(hr)) { wprintf (L"Failed to set the description, error: 0x%08X\n", hr); goto End; } // // Set a friendly name for the event - this is the display name. // hr = StringCchCopy (ReportInformation.wzFriendlyEventName, ARRAYSIZE(ReportInformation.wzFriendlyEventName), L"Sample Problem Friendly Name"); if (FAILED(hr)) { wprintf (L"Failed to set the friendly event name, error: 0x%08X\n", hr); goto End; } // // Now actually call into WER to create the report with the above structure. // We get back a handle to the report. // hr = WerReportCreate (L"SampleGenericReport", WerReportCritical, &ReportInformation, &ReportHandle); if (FAILED(hr)) { wprintf (L"WerReportCreate failed, error: 0x%08X\n", hr); goto End; } wprintf (L"Created the report.\n"); // // Now set the report parameters (3 parameters in this case). // // These parameters as used as bucketing parameters on the WER server. // hr = WerReportSetParameter(ReportHandle, 0, L"Param1", L"Value1"); if (FAILED(hr)) { wprintf (L"Set parameter failed for parameter 0, error: 0x%08X\n", hr); goto End; } hr = WerReportSetParameter(ReportHandle, 1, L"Param2", L"Value2"); if (FAILED(hr)) { wprintf (L"Set parameter failed for parameter 1, error: 0x%08X\n", hr); goto End; } hr = WerReportSetParameter(ReportHandle, 2, L"Param3", L"Value3"); if (FAILED(hr)) { wprintf (L"Set parameter failed for parameter 3, error: 0x%08X\n", hr); goto End; } // // Customize the WER UI. // // Note: See MSDN or werapi.h for the list of various UI elements. // // // Customize the problem description header. // hr = WerReportSetUIOption (ReportHandle, WerUIConsentDlgHeader, L"Sample Consent Dialog Header"); if (FAILED (hr)) { wprintf (L"WerReportSetUIOption failed, error: 0x%08X\n", hr); goto End; } wprintf (L"Successfully customized the consent dialog header.\n"); // // Customize the consent dialog body (subtext). // hr = WerReportSetUIOption (ReportHandle, WerUIConsentDlgBody, L"Sample Consent Dialog Body"); if (FAILED (hr)) { wprintf (L"WerReportSetUIOption failed, error: 0x%08X\n", hr); goto End; } wprintf (L"Successfully customized the consent dialog body.\n"); // // Customize the icon. // We'll use the icon from the Calculator program here. // hr = WerReportSetUIOption (ReportHandle, WerUIIconFilePath, L"%windir%\\system32\\calc.exe"); if (FAILED (hr)) { wprintf (L"WerReportSetUIOption failed, error: 0x%08X\n", hr); goto End; } wprintf (L"Successfully customized the icon.\n"); // // Customize the text for the online solution check. // hr = WerReportSetUIOption (ReportHandle, WerUIOnlineSolutionCheckText, L"Sample Check for Solution"); if (FAILED (hr)) { wprintf (L"WerReportSetUIOption failed, error: 0x%08X\n", hr); goto End; } wprintf (L"Successfully customized online solution check text.\n"); // // Customize the text for closing the program. // hr = WerReportSetUIOption (ReportHandle, WerUICloseText, L"Sample Close the program"); if (FAILED (hr)) { wprintf (L"WerReportSetUIOption failed, error: 0x%08X\n", hr); goto End; } wprintf (L"Successfully customized text for closing the program.\n"); // // Submit the report. // // After the application calls this API, WER collects the specified data. // hr = WerReportSubmit (ReportHandle, WerConsentNotAsked, 0, &SubmitResult); if (FAILED(hr)) { wprintf (L"WerReportSubmit failed, error: 0x%08X\n", hr); goto End; } wprintf (L"Submission result was %u (WER_SUBMIT_RESULT enum).\n", SubmitResult); hr = S_OK; End: if (ReportHandle) { // // Close the handle to the report. Call this API after report has been // submitted, or the handle is no longer needed. // hr = WerReportCloseHandle (ReportHandle); if (FAILED(hr)) { wprintf (L"WerReportCloseHandle failed, error: 0x%08X\n", hr); } } if (FAILED(hr)) { // // Return -1 to indicate that an error occured // return -1; } return 0; }