From 7f3b075ac4a95dce062c6fb01b53568682fdd7fd Mon Sep 17 00:00:00 2001 From: SomeTroglodyte <63000004+SomeTroglodyte@users.noreply.github.com> Date: Fri, 25 Mar 2022 15:29:09 +0100 Subject: [PATCH] Implement a rudimentary CrashReportSysInfoDesktop (#6400) * Implement a rudimentary CrashReportSysInfoDesktop * Now gets Windows info the hard way --- .../app/desktop/CrashReportSysInfoDesktop.kt | 100 ++++++++++++++++++ .../com/unciv/app/desktop/DesktopLauncher.kt | 3 +- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 desktop/src/com/unciv/app/desktop/CrashReportSysInfoDesktop.kt diff --git a/desktop/src/com/unciv/app/desktop/CrashReportSysInfoDesktop.kt b/desktop/src/com/unciv/app/desktop/CrashReportSysInfoDesktop.kt new file mode 100644 index 0000000000..c9936b2fbd --- /dev/null +++ b/desktop/src/com/unciv/app/desktop/CrashReportSysInfoDesktop.kt @@ -0,0 +1,100 @@ +package com.unciv.app.desktop + +import com.badlogic.gdx.files.FileHandle +import com.unciv.ui.utils.CrashReportSysInfo +import java.nio.charset.Charset + +class CrashReportSysInfoDesktop : CrashReportSysInfo { + + override fun getInfo(): String { + val builder = StringBuilder() + + // Operating system + val osName = System.getProperty("os.name") ?: "Unknown" + val isWindows = osName.startsWith("Windows", ignoreCase = true) + builder.append("OS: $osName") + if (!isWindows) { + val osInfo = listOfNotNull(System.getProperty("os.arch"), System.getProperty("os.version")).joinToString() + if (osInfo.isNotEmpty()) builder.append(" ($osInfo)") + } + builder.appendLine() + + // Specific release info + val osRelease = if (isWindows) getWinVer() else getLinuxDistro() + if (osRelease.isNotEmpty()) + builder.appendLine("\t$osRelease") + + // Java runtime version + val javaVendor: String? = System.getProperty("java.vendor") + if (javaVendor != null) { + val javaVersion: String = System.getProperty("java.vendor.version") ?: System.getProperty("java.vm.version") ?: "" + builder.appendLine("Java: $javaVendor $javaVersion") + } + + // Java VM memory limit as set by -Xmx + val maxMemory = try { + Runtime.getRuntime().maxMemory() / 1024 / 1024 + } catch (ex: Throwable) { -1L } + if (maxMemory > 0) { + builder.append('\t') + builder.appendLine("Max Memory: $maxMemory MB") + } + + return builder.toString() + } + + companion object { + @Suppress("SpellCheckingInspection") + private val winVerCommand = """ + cmd /c + reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName && + reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ReleaseId && + reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v CurrentBuild && + reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v DisplayVersion + """.trimIndent().replace('\n', ' ') + + /** Kludge to get the important Windows version info (no easier way than the registry AFAIK) + * using a subprocess running reg query. Other methods would involve nasty reflection + * to break java.util.prefs.Preferences out of its Sandbox, or JNA requiring new bindings. + */ + fun getWinVer(): String { + val entries: Map = try { + val process = Runtime.getRuntime().exec(winVerCommand) + process.waitFor() + val output = process.inputStream.readAllBytes().toString(Charset.defaultCharset()) + + val goodLines = output.split('\n').mapNotNull { + it.removeSuffix("\r").run { + if (startsWith(" ") || startsWith("\t")) trim() else null + } + } + + goodLines.map { it.split("REG_SZ") } + .filter { it.size == 2 } + .associate { it[0].trim() to it[1].trim() } + } catch (ex: Throwable) { mapOf() } + + if ("ProductName" !in entries) return "" + + return entries["ProductName"]!! + + ((entries["DisplayVersion"] ?: entries["ReleaseId"])?.run { " Version $this" } ?: "") + + (entries["CurrentBuild"]?.run { " (Build $this)" } ?: "") + } + + /** Get linux Distribution out of the /etc/os-release file (ini-style) + * Should be safely silent on systems not supporting that file. + */ + fun getLinuxDistro(): String { + val osRelease: Map = try { + FileHandle("/etc/os-release") + .readString() + .split('\n') + .map { it.split('=') } + .filter { it.size == 2 } + .associate { it[0] to it[1].removeSuffix("\"").removePrefix("\"") } + } catch (ex: Throwable) { mapOf() } + if ("NAME" !in osRelease) return "" + return osRelease["PRETTY_NAME"] ?: "${osRelease["NAME"]} ${osRelease["VERSION"]}" + } + } +} diff --git a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt index 3051342e26..f080da134f 100644 --- a/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt +++ b/desktop/src/com/unciv/app/desktop/DesktopLauncher.kt @@ -49,7 +49,8 @@ internal object DesktopLauncher { versionFromJar, cancelDiscordEvent = { discordTimer?.cancel() }, fontImplementation = NativeFontDesktop(Fonts.ORIGINAL_FONT_SIZE.toInt(), settings.fontFamily), - customSaveLocationHelper = CustomSaveLocationHelperDesktop() + customSaveLocationHelper = CustomSaveLocationHelperDesktop(), + crashReportSysInfo = CrashReportSysInfoDesktop() ) val game = UncivGame(desktopParameters)