OSDN Git Service

[Feature] Windows版で例外キャッチ時にエラー情報を送信する
authorHabu <habu1010+github@gmail.com>
Fri, 7 Jul 2023 11:33:54 +0000 (20:33 +0900)
committerHabu <habu1010+github@gmail.com>
Fri, 7 Jul 2023 13:18:36 +0000 (22:18 +0900)
Windows版で予期しない例外が発生した場合、エラー情報を送信するかどうかの
確認を行い、OKならWebhookでエラー情報を送信する。

Hengband/Hengband/Hengband.vcxproj
Hengband/Hengband/Hengband.vcxproj.filters
src/Makefile.am
src/main-win.cpp
src/main-win/main-win-exception.cpp [new file with mode: 0644]
src/main-win/main-win-exception.h [new file with mode: 0644]

index 325fb1c..af4e2fa 100644 (file)
     <ClCompile Include="..\..\src\load\item\item-loader-factory.cpp" />\r
     <ClCompile Include="..\..\src\load\monster\monster-loader-factory.cpp" />\r
     <ClCompile Include="..\..\src\load\player-class-specific-data-loader.cpp" />\r
+    <ClCompile Include="..\..\src\main-win\main-win-exception.cpp" />\r
     <ClCompile Include="..\..\src\monster-race\race-brightness-mask.cpp" />\r
     <ClCompile Include="..\..\src\monster-race\race-feature-mask.cpp" />\r
     <ClCompile Include="..\..\src\monster\monster-pain-describer.cpp" />\r
     <ClInclude Include="..\..\src\load\old\monster-flag-types-savefile50.h" />\r
     <ClInclude Include="..\..\src\load\player-class-specific-data-loader.h" />\r
     <ClInclude Include="..\..\src\load\savedata-old-flag-types.h" />\r
+    <ClInclude Include="..\..\src\main-win\main-win-exception.h" />\r
     <ClInclude Include="..\..\src\market\bounty-type-definition.h" />\r
     <ClInclude Include="..\..\src\monster-race\monster-aura-types.h" />\r
     <ClInclude Include="..\..\src\monster-race\monster-kind-mask.h" />\r
index 47f64e5..d5e0d1c 100644 (file)
     <ClCompile Include="..\..\src\net\report-error.cpp">\r
       <Filter>net</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\src\main-win\main-win-exception.cpp">\r
+      <Filter>main-win</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="..\..\src\combat\shoot.h">\r
     <ClInclude Include="..\..\src\net\report-error.h">\r
       <Filter>net</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\src\main-win\main-win-exception.h">\r
+      <Filter>main-win</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <None Include="..\..\src\wall.bmp" />\r
index bdce87e..30c0cee 100644 (file)
@@ -1040,6 +1040,7 @@ EXTRA_hengband_SOURCES = \
        main-win/main-win-bg.cpp main-win/main-win-bg.h \
        main-win/main-win-cfg-reader.cpp main-win/main-win-cfg-reader.h \
        main-win/main-win-define.h \
+       main-win/main-win-exception.cpp main-win/main-win-exception.h \
        main-win/main-win-file-utils.cpp main-win/main-win-file-utils.h \
        main-win/main-win-mci.cpp main-win/main-win-mci.h \
        main-win/main-win-menuitem.h \
index be81c6d..7185f34 100644 (file)
 #include "main-win/commandline-win.h"
 #include "main-win/graphics-win.h"
 #include "main-win/main-win-bg.h"
+#include "main-win/main-win-exception.h"
 #include "main-win/main-win-file-utils.h"
 #include "main-win/main-win-mci.h"
 #include "main-win/main-win-menuitem.h"
@@ -2756,10 +2757,9 @@ static void register_wndclass(void)
 }
 
 /*!
- * @brief (Windows固有)Windowsアプリケーションとしてのエントリポイント
+ * @brief ゲームのメインルーチン
  */
-int WINAPI WinMain(
-    _In_ HINSTANCE hInst, [[maybe_unused]] _In_opt_ HINSTANCE hPrevInst, [[maybe_unused]] _In_ LPSTR lpCmdLine, [[maybe_unused]] _In_ int nCmdShow)
+int WINAPI game_main(_In_ HINSTANCE hInst)
 {
     setlocale(LC_ALL, "ja_JP");
     hInstance = hInst;
@@ -2848,4 +2848,19 @@ int WINAPI WinMain(
     quit(nullptr);
     return 0;
 }
+
+/*!
+ * @brief (Windows固有)Windowsアプリケーションとしてのエントリポイント
+ */
+int WINAPI WinMain(
+    _In_ HINSTANCE hInst, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int)
+{
+    try {
+        return game_main(hInst);
+    } catch (const std::exception &e) {
+        handle_unexpected_exception(e);
+        return 1;
+    }
+}
+
 #endif /* WINDOWS */
diff --git a/src/main-win/main-win-exception.cpp b/src/main-win/main-win-exception.cpp
new file mode 100644 (file)
index 0000000..d88fe7f
--- /dev/null
@@ -0,0 +1,43 @@
+#include "main-win/main-win-exception.h"
+#include "main-win/main-win-utils.h"
+#include "net/report-error.h"
+#include <sstream>
+
+/*!
+ * @brief 予期しない例外を処理する
+ *
+ * 予期しない例外が発生した場合、確認を取り例外のエラー情報を開発チームに送信する。
+ * その後、バグ報告ページを開くかどうか尋ね、開く場合はWebブラウザで開く。
+ *
+ * @param e 例外オブジェクト
+ */
+void handle_unexpected_exception(const std::exception &e)
+{
+    constexpr auto caption = _(L"予期しないエラー!", L"Unexpected error!");
+
+#if !defined(DISABLE_NET)
+    std::wstringstream report_confirm_msg_ss;
+    report_confirm_msg_ss
+        << to_wchar(e.what()).wc_str() << L"\n\n"
+        << _(L"開発チームにエラー情報を送信してよろしいですか?\n", L"Are you sure you want to send the error information to the development team?\n")
+        << _(L"※送信されるのはゲーム内の情報のみであり、個人情報が送信されることはありません。\n",
+               L"Only in-game information will be sent. No personal information will be sent.\n");
+
+    if (auto choice = MessageBoxW(NULL, report_confirm_msg_ss.str().data(), caption, MB_ICONEXCLAMATION | MB_YESNO | MB_ICONSTOP);
+        choice == IDYES) {
+        report_error(e.what());
+    }
+#endif
+
+    std::wstringstream issue_page_open_msg_ss;
+    issue_page_open_msg_ss
+        << _(L"エラー発生の詳しい状況を報告してくださると助かります。\n",
+               L"It would be helpful if you could report the detailed circumstances of the error.\n")
+        << _(L"バグ報告ページを開きますか?\n", L"Open bug report page?\n");
+
+    if (auto choice = MessageBoxW(NULL, issue_page_open_msg_ss.str().data(), caption, MB_ICONEXCLAMATION | MB_YESNO | MB_ICONSTOP);
+        choice == IDYES) {
+        constexpr auto url = "https://github.com/hengband/hengband/issues/new/choose";
+        ShellExecuteA(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
+    }
+};
diff --git a/src/main-win/main-win-exception.h b/src/main-win/main-win-exception.h
new file mode 100644 (file)
index 0000000..524cd20
--- /dev/null
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <stdexcept>
+
+void handle_unexpected_exception(const std::exception &e);