public static void GenerateReport()
        {
            var sb = new StringBuilder();

            try {
                sb.AppendLine("Recorded Unhandled Exceptions:");
                var i = 0;
                foreach (var exc in RecordedUnhandledExceptions)
                {
                    var excStr = exc.ToString();
                    sb.Append("  ").Append(++i).Append(". ").AppendLine(excStr.Replace("\n", "\n    "));
                    var iex = exc;
                    var j   = 0;
                    while (iex.InnerException != null)
                    {
                        iex = iex.InnerException;
                        sb.Append("    ").Append(i).Append(".").Append(++j).Append(". ").AppendLine(excStr.Replace("\n", "\n    "));
                    }
                }

                if (i == 0)
                {
                    sb.AppendLine("  None.");
                }
            }
            catch (Exception ex) {
                sb.Append("  *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message);
            }

            sb.AppendLine();

            try {
                sb.AppendLine("Recorded First Chance Exceptions:");
                var i = 0;
                foreach (var exc in RecordedFirstChanceExceptions)
                {
                    var excStr = exc.ToString();
                    sb.Append("  ").Append(++i).Append(". ").AppendLine(excStr.Replace("\n", "\n    "));
                    var iex = exc;
                    var j   = 0;
                    while (iex.InnerException != null)
                    {
                        iex = iex.InnerException;
                        sb.Append("    ").Append(i).Append(".").Append(++j).Append(". ").AppendLine(excStr.Replace("\n", "\n    "));
                    }
                }

                if (RecordFirstChanceExceptions)
                {
                    if (i == 0)
                    {
                        sb.AppendLine("  None recorded.");
                    }
                }
                else
                {
                    sb.AppendLine("  Recording disabled.");
                }
            }
            catch (Exception ex) {
                sb.Append("  *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message);
            }

            sb.AppendLine();

            try {
                sb.AppendLine("Modules Information:");
                var i = 0;
                foreach (var mi in ModuleInfo.GetModules())
                {
                    sb.Append("  ").Append(++i).Append(". ").Append(mi.Id).Append(" ").Append(mi.Version.ToString());
                    if (mi.IsSelected)
                    {
                        sb.Append(" *Selected*");
                    }
                    sb.AppendLine();
                    sb.Append("    ").Append(mi.Name);
                    if (!String.IsNullOrWhiteSpace(mi.Alias))
                    {
                        sb.Append(" (").Append(mi.Alias).Append(")");
                    }
                    if (mi.IsOfficial)
                    {
                        sb.Append(" *Official*");
                    }
                    sb.AppendLine();
                    if (mi.DependedModuleIds.Count <= 0)
                    {
                        continue;
                    }

                    sb.Append("  ").AppendLine("Dependencies:");
                    var j = 0;
                    foreach (var dep in mi.DependedModuleIds)
                    {
                        sb.Append("    ").Append(++j).Append(". ").AppendLine(dep);
                    }
                }
            }
            catch (Exception ex) {
                sb.Append("  *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message);
            }

            sb.AppendLine();

            try {
                sb.AppendLine("Harmony Patch Information:");
                var i = 0;
                foreach (var patchedMethod in Harmony.GetAllPatchedMethods())
                {
                    var patchInfo = Harmony.GetPatchInfo(patchedMethod);
                    sb.Append("  ").Append(++i).Append(". ").AppendLine(patchedMethod.FullDescription());

                    if (patchInfo.Prefixes.Count > 0)
                    {
                        var j = 0;
                        sb.Append("    ").AppendLine("Prefixes:");
                        foreach (var patch in patchInfo.Prefixes)
                        {
                            sb.Append("      ").Append(++j).Append(". ").AppendLine(patch.PatchMethod.FullDescription());
                            sb.Append("        ").AppendLine($"Owner: {patch.owner}, Priority: {patch.priority}");
                        }
                    }

                    if (patchInfo.Postfixes.Count > 0)
                    {
                        var j = 0;
                        sb.Append("    ").AppendLine("Postfixes:");
                        foreach (var patch in patchInfo.Postfixes)
                        {
                            sb.Append("      ").Append(++j).Append(". ").AppendLine(patch.PatchMethod.FullDescription());
                            sb.Append("        ").AppendLine($"Owner: {patch.owner}, Priority: {patch.priority}");
                        }
                    }

                    if (patchInfo.Finalizers.Count > 0)
                    {
                        var j = 0;
                        sb.Append("    ").AppendLine("Finalizers:");
                        foreach (var patch in patchInfo.Finalizers)
                        {
                            sb.Append("      ").Append(++j).Append(". ").AppendLine(patch.PatchMethod.FullDescription());
                            sb.Append("        ").AppendLine($"Owner: {patch.owner}, Priority: {patch.priority}");
                        }
                    }

                    if (patchInfo.Transpilers.Count > 0)
                    {
                        var j = 0;
                        sb.Append("    ").AppendLine("Transpilers:");
                        foreach (var patch in patchInfo.Transpilers)
                        {
                            sb.Append("      ").Append(++j).Append(". ").AppendLine(patch.PatchMethod.FullDescription());
                            sb.Append("        ").AppendLine($"Owner: {patch.owner}, Priority: {patch.priority}");
                        }
                    }
                }
            }
            catch (Exception ex) {
                sb.Append("  *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message);
            }

            sb.AppendLine();

            try {
                sb.AppendLine("Community Patch Information:");
                var i = 0;
                foreach (var patch in CommunityPatchSubModule.Patches)
                {
                    var type = patch.GetType();
                    sb.Append("  ").Append(++i).Append(". ").Append(type.Name);
                    if (ActivePatches.ContainsKey(type))
                    {
                        sb.Append(" *Active*");
                    }
                    var applicability = patch.IsApplicable(Game.Current);
                    if (applicability ?? false)
                    {
                        sb.Append(" *Applicable*");
                    }
                    if (applicability == null)
                    {
                        sb.Append(" *Maybe Applicable*");
                    }
                    if (patch.Applied)
                    {
                        sb.Append(" *Applied*");
                    }
                    sb.AppendLine();
                }
            }
            catch (Exception ex) {
                sb.Append("  *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message);
            }

            sb.AppendLine();

            try {
                sb.AppendLine("Loaded SubModules:");
                var i = 0;
                foreach (var sm in Module.CurrentModule.SubModules)
                {
                    try {
                        var type = sm.GetType();
                        var asm  = type.Assembly;
                        sb.Append("  ").Append(++i).Append(". ").AppendLine(type.AssemblyQualifiedName);
                        foreach (var version in asm.GetCustomAttributes <AssemblyInformationalVersionAttribute>())
                        {
                            sb.Append("    v").AppendLine(version.InformationalVersion);
                        }
                    }
                    catch (Exception ex) {
                        sb.Append("  *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message);
                    }
                }
            }
            catch (Exception ex) {
                sb.Append("  *** ERROR: ").Append(ex.GetType().Name).Append(": ").AppendLine(ex.Message);
            }

            sb.AppendLine();

            AppendSystemReport(sb);

            try {
                var reportStr = sb.ToString();

                ShowMessage("Saving to \"My Documents\\Mount and Blade II Bannerlord\\diagnostic-report.txt\"");

                try {
                    var docsMnb2 = new Uri(System.IO.Path.Combine(PathHelpers.GetConfigsDir(), "..")).LocalPath;
                    var now      = DateTime.UtcNow;
                    Random.GetNonZeroBytes(RandomIntBuf);
                    var randomInt = Unsafe.ReadUnaligned <uint>(ref RandomIntBuf[0]);
                    File.WriteAllText(System.IO.Path.Combine(docsMnb2, $"diagnostic-report.{now.Year:0000}{now.Month:00}{now.Day:00}{now.Hour:00}{now.Minute:00}{now.Second:00}{now.Millisecond}.{randomInt:X8}.txt"), reportStr);
                }
                catch (Exception ex2) {
                    ShowMessage($"Failed to save diagnostic report!\n{ex2.GetType().Name}: {ex2.Message}");
                }

                try {
                    Input.SetClipboardText(reportStr);
                    ShowMessage("Diagnostics also copied to system clipboard.");
                }
                catch (Exception ex) {
                    ShowMessage($"Writing to system clipboard failed!\n{ex.GetType().Name}: {ex.Message}");
                }
            }
            catch (Exception ex) {
                ShowMessage($"Failed to generate string from diagnostic report string buffer!\n{ex.GetType().Name}: {ex.Message}");
            }
        }