134 lines
4.2 KiB
C#
134 lines
4.2 KiB
C#
using System.Runtime.InteropServices;
|
|
using Windows.ApplicationModel;
|
|
using YMhut.Box.Core.App;
|
|
|
|
namespace YMhut.Box.WinUI.Services;
|
|
|
|
internal static class RuntimeLayoutBootstrapper
|
|
{
|
|
public static bool TryRelaunchFromWritableLayoutIfNeeded()
|
|
{
|
|
try
|
|
{
|
|
CleanupLegacyPersistentRuntime();
|
|
if (IsPackaged() || !RequiresLegacyCompressedLayout(AppContext.BaseDirectory))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
const string title = "YMhut Box 启动失败";
|
|
var message =
|
|
"检测到旧版压缩语言资源布局,YMhut Box 不再把运行时复制到用户目录。\n\n" +
|
|
"请使用新版安装包覆盖安装。安装引导程序会清理旧布局并重新铺设程序文件。\n\n" +
|
|
"This installation still uses the legacy compressed language layout. YMhut Box no longer creates a persistent runtime copy under LocalAppData. Please reinstall with the latest setup package.";
|
|
CrashLog.Write(message);
|
|
ShowStartupError(title, message);
|
|
return true;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
CrashLog.Write(exception);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static string InstalledExecutablePath => InstallLayoutPaths.ResolveInstalledExecutablePath();
|
|
|
|
public static string InstalledWorkingDirectory => Path.GetDirectoryName(InstalledExecutablePath) ?? AppContext.BaseDirectory;
|
|
|
|
private static bool RequiresLegacyCompressedLayout(string directory)
|
|
{
|
|
var legacyLangRoot = Path.Combine(directory, "resources", "lang");
|
|
return Directory.Exists(legacyLangRoot) &&
|
|
Directory.EnumerateFiles(legacyLangRoot, "*.bin", SearchOption.TopDirectoryOnly).Any() &&
|
|
!HasPureLangSatelliteResources(directory);
|
|
}
|
|
|
|
private static bool HasPureLangSatelliteResources(string directory)
|
|
{
|
|
var langRoot = Path.Combine(directory, "lang");
|
|
if (!Directory.Exists(langRoot))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
foreach (var culture in new[] { "zh-CN", "en-US" })
|
|
{
|
|
var cultureRoot = Path.Combine(langRoot, culture);
|
|
if (!Directory.Exists(cultureRoot))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!Directory.EnumerateFiles(cultureRoot, "*.mui", SearchOption.AllDirectories).Any() &&
|
|
!Directory.EnumerateFiles(cultureRoot, "*.resources.dll", SearchOption.AllDirectories).Any())
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private static void CleanupLegacyPersistentRuntime()
|
|
{
|
|
var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
|
var legacyRoots = new[]
|
|
{
|
|
Path.Combine(localAppData, "YMhut Box", "WinUI"),
|
|
Path.Combine(localAppData, "YMhut Box"),
|
|
Path.Combine(localAppData, "ymhut_box")
|
|
};
|
|
|
|
foreach (var root in legacyRoots)
|
|
{
|
|
foreach (var name in AppPaths.RuntimePayloadDirectoryNames)
|
|
{
|
|
TryDeleteDirectory(Path.Combine(root, name));
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void TryDeleteDirectory(string directory)
|
|
{
|
|
try
|
|
{
|
|
if (Directory.Exists(directory))
|
|
{
|
|
Directory.Delete(directory, recursive: true);
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
CrashLog.Write($"Unable to remove legacy runtime directory '{directory}': {exception.Message}");
|
|
}
|
|
}
|
|
|
|
private static bool IsPackaged()
|
|
{
|
|
try
|
|
{
|
|
_ = Package.Current.Id.FullName;
|
|
return true;
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static void ShowStartupError(string title, string message)
|
|
{
|
|
try
|
|
{
|
|
_ = MessageBoxW(IntPtr.Zero, message, title, 0x00000010);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = false)]
|
|
private static extern int MessageBoxW(IntPtr hWnd, string text, string caption, uint type);
|
|
}
|