/** * Find the error report folder and check it matches the app name if provided */ FPlatformErrorReport LoadErrorReport() { if (ReportDirectoryAbsolutePath.IsEmpty()) { UE_LOG(CrashReportClientLog, Warning, TEXT("No error report found")); return FPlatformErrorReport(); } FPlatformErrorReport ErrorReport(ReportDirectoryAbsolutePath); FString XMLWerFilename; ErrorReport.FindFirstReportFileWithExtension( XMLWerFilename, TEXT( ".xml" ) ); extern FCrashDescription& GetCrashDescription(); GetCrashDescription() = FCrashDescription( ReportDirectoryAbsolutePath / XMLWerFilename ); #if CRASH_REPORT_UNATTENDED_ONLY return ErrorReport; #else if( !GameNameFromCmd.IsEmpty() && GameNameFromCmd != GetCrashDescription().GameName ) { // Don't display or upload anything if it's not the report we expected ErrorReport = FPlatformErrorReport(); } return ErrorReport; #endif }
void FCrashReportClient::AllowToBeContacted_OnCheckStateChanged( ECheckBoxState NewRadioState ) { FCrashReportClientConfig::Get().SetAllowToBeContacted( NewRadioState == ECheckBoxState::Checked ); // Refresh PII based on the bAllowToBeContacted flag. GetCrashDescription().UpdateIDs(); // Update diagnostics text. FormattedDiagnosticText = FCrashReportUtil::FormatDiagnosticText( DiagnosticText, GetCrashDescription().MachineId, GetCrashDescription().EpicAccountId, GetCrashDescription().UserName ); }
void FCrashReportClient::FinalizeDiagnoseReportWorker( FText ReportText ) { DiagnosticText = ReportText; FormattedDiagnosticText = FCrashReportUtil::FormatDiagnosticText( ReportText, GetCrashDescription().MachineId, GetCrashDescription().EpicAccountId, GetCrashDescription().UserName ); auto DiagnosticsFilePath = ErrorReport.GetReportDirectory() / FCrashReportClientConfig::Get().GetDiagnosticsFilename(); Uploader.LocalDiagnosisComplete(FPaths::FileExists(DiagnosticsFilePath) ? DiagnosticsFilePath : TEXT("")); }
FReply FCrashReportClient::SubmitAndRestart() { Submit(); const FString CrashedAppPath = ErrorReport.FindCrashedAppPath(); const FCrashDescription& CrashDescription = GetCrashDescription(); const FString CommandLineArguments = CrashDescription.CommandLine; FPlatformProcess::CreateProc(*CrashedAppPath, *CommandLineArguments, true, false, false, NULL, 0, NULL, NULL); return FReply::Handled(); }
FReply FCrashReportClient::Submit() { if (ErrorReport.HasFilesToUpload()) { // Send analytics. GetCrashDescription().SendAnalytics(); } bSendData = true; StoreCommentAndUpload(); bShouldWindowBeHidden = true; return FReply::Handled(); }
FCrashReportClient::FCrashReportClient(const FPlatformErrorReport& InErrorReport) : DiagnosticText( LOCTEXT("ProcessingReport", "Processing crash report ...") ) , DiagnoseReportTask(nullptr) , ErrorReport( InErrorReport ) , Uploader( FCrashReportClientConfig::Get().GetReceiverAddress() ) , bBeginUploadCalled(false) , bShouldWindowBeHidden(false) , bSendData(false) { if (!ErrorReport.TryReadDiagnosticsFile(DiagnosticText) && !FParse::Param(FCommandLine::Get(), TEXT("no-local-diagnosis"))) { DiagnoseReportTask = new FAsyncTask<FDiagnoseReportWorker>( this ); DiagnoseReportTask->StartBackgroundTask(); } else if( !DiagnosticText.IsEmpty() ) { FormattedDiagnosticText = FCrashReportUtil::FormatDiagnosticText( DiagnosticText, GetCrashDescription().MachineId, GetCrashDescription().EpicAccountId, GetCrashDescription().UserName ); } }
void RunCrashReportClient(const TCHAR* CommandLine) { // Override the stack size for the thread pool. FQueuedThreadPool::OverrideStackSize = 256 * 1024; // Set up the main loop GEngineLoop.PreInit(CommandLine); // Initialize config. FCrashReportClientConfig::Get(); const bool bUnattended = #if CRASH_REPORT_UNATTENDED_ONLY true; #else FApp::IsUnattended(); #endif // CRASH_REPORT_UNATTENDED_ONLY // Set up the main ticker FMainLoopTiming MainLoop(IdealTickRate, bUnattended ? EMainLoopOptions::CoreTickerOnly : EMainLoopOptions::UsingSlate); // Find the report to upload in the command line arguments ParseCommandLine(CommandLine); // Increase the HttpSendTimeout to 5 minutes GConfig->SetFloat(TEXT("HTTP"), TEXT("HttpSendTimeout"), 5*60.0f, GEngineIni); FPlatformErrorReport::Init(); auto ErrorReport = LoadErrorReport(); if( ErrorReport.HasFilesToUpload() ) { // Send analytics. extern FCrashDescription& GetCrashDescription(); GetCrashDescription().SendAnalytics(); } if (bUnattended) { ErrorReport.SetUserComment( NSLOCTEXT( "CrashReportClient", "UnattendedMode", "Sent in the unattended mode" ), false ); FCrashReportClientUnattended CrashReportClient( ErrorReport ); // loop until the app is ready to quit while (!GIsRequestingExit) { MainLoop.Tick(); } } else { #if !CRASH_REPORT_UNATTENDED_ONLY // crank up a normal Slate application using the platform's standalone renderer FSlateApplication::InitializeAsStandaloneApplication(GetStandardStandaloneRenderer()); // Prepare the custom Slate styles FCrashReportClientStyle::Initialize(); // Create the main implementation object TSharedRef<FCrashReportClient> CrashReportClient = MakeShareable(new FCrashReportClient(ErrorReport)); // open up the app window TSharedRef<SCrashReportClient> ClientControl = SNew(SCrashReportClient, CrashReportClient); auto Window = FSlateApplication::Get().AddWindow( SNew(SWindow) .Title(NSLOCTEXT("CrashReportClient", "CrashReportClientAppName", "Unreal Engine 4 Crash Reporter")) .ClientSize(InitialWindowDimensions) [ ClientControl ]); Window->SetRequestDestroyWindowOverride(FRequestDestroyWindowOverride::CreateSP(CrashReportClient, &FCrashReportClient::RequestCloseWindow)); // Setting focus seems to have to happen after the Window has been added FSlateApplication::Get().ClearKeyboardFocus(EFocusCause::Cleared); // Debugging code if (RunWidgetReflector) { FSlateApplication::Get().AddWindow( SNew(SWindow) .ClientSize(FVector2D(800, 600)) [ FModuleManager::LoadModuleChecked<ISlateReflectorModule>("SlateReflector").GetWidgetReflector() ]); } // loop until the app is ready to quit while (!GIsRequestingExit) { MainLoop.Tick(); if (CrashReportClient->ShouldWindowBeHidden()) { Window->HideWindow(); } } // Clean up the custom styles FCrashReportClientStyle::Shutdown(); // Close down the Slate application FSlateApplication::Shutdown(); #endif // !CRASH_REPORT_UNATTENDED_ONLY } FPlatformErrorReport::ShutDown(); FEngineLoop::AppPreExit(); FTaskGraphInterface::Shutdown(); FEngineLoop::AppExit(); }
FString FCrashReportClient::GetCrashedAppName() const { return GetCrashDescription().GameName; }