Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 6 additions & 22 deletions src/KKManager.Core/Functions/DebugInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static class DebugInfo
public static void GenerateDebugInfo(string atPath)
{
var epoch = new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString();
var tempDebugDir = Directory.CreateDirectory(Path.Combine(atPath, $"DebugInfoTemp {epoch}"));
var tempDebugDir = Directory.CreateDirectory(Path.Combine(atPath, $"DebugInfoTemp {epoch}"));

try
{
Expand All @@ -21,10 +21,10 @@ public static void GenerateDebugInfo(string atPath)
ZipPluginsAndConfig(Path.Combine(tempDebugDir.FullName, "Bepin.zip"));

GetLogs(tempDebugDir);

ZipFile.CreateFromDirectory(tempDebugDir.FullName, Path.Combine(atPath,
$"{InstallDirectoryHelper.GameType.GetFancyGameName()} Debug Info {epoch}.zip"));
}
}
finally
{
tempDebugDir.Delete(true);
Expand Down Expand Up @@ -81,8 +81,8 @@ private static void ListFilesInDirectory(DirectoryInfo dirInfo, int depth, Strin
var nameLength = 0;
foreach (var file in files)
{
if (file.Name.Length > nameLength)
{
if (file.Name.Length > nameLength)
{
nameLength = file.Name.Length; //This doesn't handle multibyte Unicode characters correctly
}
}
Expand Down Expand Up @@ -153,26 +153,10 @@ private static string RelativePath(string fullPath, string pathRelativeTo)

private static void GetLogs(DirectoryInfo debugDirInfo)
{
var logOutputFiles = InstallDirectoryHelper.GameDirectory.EnumerateFiles("LogOutput.log*", SearchOption.AllDirectories).ToArray();
var outputLogFiles = InstallDirectoryHelper.GameDirectory.EnumerateFiles("output_log.txt", SearchOption.AllDirectories).ToArray();

if (outputLogFiles.Length == 0)
{
//We are probably on one of the games that logs to AppData/LocalLow, and the user hasn't configured Doorstop to redirect the logs.
//For now just log that this happens instead of trying to traverse the AppData folder (since we'd have to determine the subfolder name in AppData anyway)
Console.WriteLine("Could not locate output_log.txt! Check if redirect_output_log is set to true in doorstop_config.ini");
}
var logOutputFiles = InstallDirectoryHelper.FindLogFiles(true);

foreach (var logFile in logOutputFiles)
{
logFile.CopyTo(Path.Combine(debugDirInfo.FullName, logFile.Name), true);
}

foreach (var outputFile in outputLogFiles)
{
var uniqueName = $"{outputFile.Directory.Name} {outputFile.Name}"; //There may be be multiple output_logs so we have to differentiate them
outputFile.CopyTo(Path.Combine(debugDirInfo.FullName, uniqueName), true);
}
}
Comment thread
ManlyMarco marked this conversation as resolved.
}
}
88 changes: 64 additions & 24 deletions src/KKManager.Core/Functions/InstallDirectoryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO;
using System.Linq;
using System.Windows.Forms;
using KKManager.Util;

namespace KKManager.Functions
{
Expand Down Expand Up @@ -197,38 +198,77 @@ public static void OpenLog()
{
try
{
bool TryOpen(string path)
{
if (path == null) return false;
try
{
Process.Start(path);
return true;
}
catch
{
return false;
}
}

var rootDir = GameDirectory.FullName;
var candidates = new List<string>();
var candidates = FindLogFiles(true);

// BepInEx 5.x log file, can be "LogOutput.log.1" or higher if multiple game instances run.
candidates.AddRange(Directory.GetFiles(rootDir, "LogOutput.log*", SearchOption.AllDirectories));
// Unity built-in log file, by default inside _Data dir, disabled, or somewhere in appdata. Can be moved to game root by BepInEx preloader if configured.
candidates.AddRange(Directory.GetFiles(rootDir, "output_log.txt", SearchOption.AllDirectories));
if (!candidates.Any())
throw new FileNotFoundException("No log files were found");

var latestLog = candidates.Where(File.Exists).OrderByDescending(File.GetLastWriteTimeUtc).FirstOrDefault();
if (TryOpen(latestLog)) return;

throw new FileNotFoundException("No log files were found");
foreach (var candidate in candidates.Take(3))
Process.Start(candidate.FullName);
}
catch (Exception exception)
{
Console.WriteLine(exception);
MessageBox.Show(string.Format(Resources.OpenGameLogFailedMessage, exception.Message), Resources.OpenGameLogMessageTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

private static readonly Dictionary<GameType, string> _AppdataRelativePaths = new Dictionary<GameType, string>
Comment thread
ManlyMarco marked this conversation as resolved.
{
{ GameType.Koikatsu , @"illusion__Koikatu\Koikatu"},
{ GameType.KoikatsuSteam , @"illusion__Koikatsu\Koikatsu Party"},
{ GameType.KoikatsuSunshine , @"illusion__KoikatsuSunshine\KoikatsuSunshine"},
{ GameType.EmotionCreators , @"illusion__EmotionCreators\EmotionCreators"},

{ GameType.AiShoujo ,@"illusion__AI-Syoujyo\AI-Syoujyo"},
{ GameType.AiShoujoSteam ,@"illusion__AI-Shoujo\AI-Shoujo"},
{ GameType.HoneySelect2 , @"illusion__HoneySelect2\HoneySelect2"}, //TODO: illusion__HoneySelect2_Steam\HoneySelect2_Steam

{ GameType.RoomGirl, @"illusion__RoomGirl\RoomGirl" },
// VR_Kanojo ILLUSION\VR_Kanojo

{ GameType.HoneyCome ,@"ILLGAMES\HoneyCome"},
{ GameType.HoneyComeSteam ,@"ILLGAMES\HoneyComeccp"},
{ GameType.SamabakeScramble , @"ILLGAMES\SamabakeScramble"},
{ GameType.Aicomi, @"ILLGAMES\Aicomi" },
};

/// <summary>
/// Finds log files for the current game.
/// </summary>
/// <param name="filter">Whether to filter the log files to only include the latest ones. If true, results are ordered by last write time (descending).</param>
/// <returns>A list of log files for the current game.</returns>
public static List<FileInfo> FindLogFiles(bool filter)
{
var candidates = new List<FileInfo>();
// BepInEx 5.x log file, can be "LogOutput.log.1" or higher if multiple game instances run.
candidates.AddRange(GameDirectory.GetFiles("LogOutput.log*", SearchOption.AllDirectories));
// Unity built-in log file, by default inside _Data dir, disabled, or somewhere in appdata. Can be moved to game root by BepInEx preloader if configured.
candidates.AddRange(GameDirectory.GetFiles("output_log.txt", SearchOption.AllDirectories));
// Check for log files stored in AppData/LocalLow in case they were not redirected by preloader config
if (_AppdataRelativePaths.TryGetValue(GameType, out var relativePath))
{
var localLow = PathTools.GetAppDataLocalLowPath();
var appdataLogPath = Path.Combine(localLow, relativePath);
if (Directory.Exists(appdataLogPath))
{
// It can be either Player.log or output_log.txt depending on Unity version
candidates.AddRange(Directory.GetFiles(appdataLogPath, "Player.log", SearchOption.AllDirectories).Select(x => new FileInfo(x)));
candidates.AddRange(Directory.GetFiles(appdataLogPath, "output_log.txt", SearchOption.AllDirectories).Select(x => new FileInfo(x)));
}
}

if (filter)
{
candidates = candidates
// Only keep the latest log file for each name (e.g. in case output_log.txt is both in game root and in appdata)
.GroupBy(x => x.Name).Select(z => z.OrderByDescending(x => x.LastWriteTimeUtc).ThenByDescending(x => x.CreationTimeUtc).First())
// Order by last write time to have the most recent log on top (e.g. in case output_log.txt and LogOutput.log both exist)
.OrderByDescending(x => x.LastWriteTimeUtc).ThenByDescending(x => x.CreationTimeUtc)
.ToList();
}

return candidates;
}
}
}
27 changes: 27 additions & 0 deletions src/KKManager.Core/Util/PathTools.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

namespace KKManager.Util
Expand Down Expand Up @@ -136,5 +137,31 @@ public static string AdjustFormat(string value)
}
return new string(a);
}

public static string GetAppDataLocalLowPath()
{
Guid localLowId = new Guid("A520A1A4-1780-4FF6-BD18-167343C5AF16");
return GetKnownFolderPath(localLowId);
}

private static string GetKnownFolderPath(Guid knownFolderId)
{
IntPtr pszPath = IntPtr.Zero;
try
{
int hr = SHGetKnownFolderPath(knownFolderId, 0, IntPtr.Zero, out pszPath);
if (hr >= 0)
return Marshal.PtrToStringAuto(pszPath);
throw Marshal.GetExceptionForHR(hr);
}
finally
{
if (pszPath != IntPtr.Zero)
Marshal.FreeCoTaskMem(pszPath);
}
}

[DllImport("shell32.dll")]
private static extern int SHGetKnownFolderPath( [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath);
}
}
26 changes: 13 additions & 13 deletions src/KKManager/Windows/MainWindow.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading