diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index 6cc322ec94..1b06aa3f5b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -50,6 +50,7 @@ import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.logging.Logger; import org.jackhuang.hmcl.util.platform.*; +import org.jackhuang.hmcl.util.platform.windows.WindowsEvents; import java.io.IOException; import java.lang.management.ManagementFactory; @@ -59,6 +60,7 @@ import java.nio.file.attribute.FileTime; import java.time.Instant; import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -290,6 +292,22 @@ private void exportGameCrashInfo() { } }); + var events = WindowsEvents.getApplicationEvents(); + var javaEvents = events.stream().filter((it) -> it != null && it.message() != null && (it.message().contains("java.exe") || it.message().contains("javaw.exe"))).toList(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + + if (!javaEvents.isEmpty()) { + javaEvents.forEach(it -> { + Instant compareInstant = LocalDateTime.parse(it.timeCreated(), formatter).atZone(ZoneId.systemDefault()).toInstant(); + if (compareInstant.toEpochMilli() > processStartTime) { + LOG.info("Found java event"); + LOG.info(String.format("ID: %d | Level: %s | Time: %s", + it.eventId(), it.level(), it.timeCreated())); + LOG.info("Message: " + it.message()); + } + }); + } + return LogExporter.exportLogs(logFile, repository, launchOptions.getVersionName(), logs, new CommandBuilder().addAll(managedProcess.getCommands()).toString(), path -> { diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WindowsEvents.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WindowsEvents.java new file mode 100644 index 0000000000..c197c3f66c --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WindowsEvents.java @@ -0,0 +1,43 @@ +package org.jackhuang.hmcl.util.platform.windows; + +import com.google.gson.reflect.TypeToken; +import org.jackhuang.hmcl.util.gson.JsonUtils; +import org.jackhuang.hmcl.util.platform.SystemUtils; + +import java.util.ArrayList; +import java.util.List; + +import static org.jackhuang.hmcl.util.logging.Logger.LOG; + +public final class WindowsEvents { + private WindowsEvents() { + throw new AssertionError(); + } + + private static final String psCommand = "Get-WinEvent -MaxEvents 50 -FilterHashtable @{LogName='Application'} | ForEach-Object { " + " [PSCustomObject]@{ " + " timeCreated = $_.TimeCreated.ToString('yyyy-MM-dd HH:mm:ss'); " + " level = $_.LevelDisplayName; " + " source = $_.ProviderName; " + " eventId = $_.Id; " + " message = $_.Message; " + " rawXml = $_.ToXml() " + " } " + "} | ConvertTo-Json -Compress"; + + + public record LogEntry(String timeCreated, String level, String source, int eventId, String message) { + } + + public static List getApplicationEvents() { + List results = new ArrayList<>(); + + try { + String rawJson = SystemUtils.run("powershell.exe", "-NoProfile", "-Command", psCommand).trim(); + + if (!rawJson.isEmpty()) { + if (rawJson.startsWith("{")) { + results.add(JsonUtils.fromNonNullJson(rawJson, LogEntry.class)); + } else if (rawJson.startsWith("[")) { + results = JsonUtils.fromNonNullJson(rawJson, new TypeToken<>() { + }); + } + } + } catch (Exception e) { + LOG.warning("Failed to fetch application logs", e); + } + return results; + } +} +