Resolve dev paths and fix splash UI thread

Compute a solutionRoot and expand development search paths (LanMountainDesktop and dev-test) in DeploymentLocator, add logging when scanning/finding hosts, and return distinct full paths. Ensure backward-compatible path checks. Fix cross-thread UI calls: invoke splashWindow.DismissAsync on the UI thread in LauncherFlowCoordinator, and make SplashWindow.DismissAsync ensure it runs on the UI thread before closing (simplified Close call). These changes improve development host discovery and prevent UI-thread access issues during shutdown.
This commit is contained in:
lincube
2026-04-24 10:05:30 +08:00
parent 9de93d2a4d
commit 28f41cd27c
3 changed files with 37 additions and 27 deletions

View File

@@ -1,4 +1,4 @@
using System.Globalization; using System.Globalization;
using System.Text.Json; using System.Text.Json;
using LanMountainDesktop.Launcher.Models; using LanMountainDesktop.Launcher.Models;
using LanMountainDesktop.Shared.Contracts.Launcher; using LanMountainDesktop.Shared.Contracts.Launcher;
@@ -360,51 +360,59 @@ internal sealed class DeploymentLocator
/// </summary> /// </summary>
private static string? ScanDevelopmentPaths(string executable) private static string? ScanDevelopmentPaths(string executable)
{ {
var solutionRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", ".."));
var possiblePaths = new[] var possiblePaths = new[]
{ {
// 浠?Launcher 椤圭洰杩愯 // 标准开发路径:解决方案根目录下的 LanMountainDesktop 项目
Path.Combine(solutionRoot, "LanMountainDesktop", "bin", "Debug", "net10.0", executable),
Path.Combine(solutionRoot, "LanMountainDesktop", "bin", "Release", "net10.0", executable),
// 向后兼容
Path.Combine(AppContext.BaseDirectory, "..", "..", "LanMountainDesktop", "bin", "Debug", "net10.0", executable), Path.Combine(AppContext.BaseDirectory, "..", "..", "LanMountainDesktop", "bin", "Debug", "net10.0", executable),
Path.Combine(AppContext.BaseDirectory, "..", "..", "LanMountainDesktop", "bin", "Release", "net10.0", executable), Path.Combine(AppContext.BaseDirectory, "..", "..", "LanMountainDesktop", "bin", "Release", "net10.0", executable),
// 浠庤В鍐虫柟妗堟牴鐩綍杩愯 // dev-test 目录
Path.Combine(AppContext.BaseDirectory, "..", "LanMountainDesktop", "bin", "Debug", "net10.0", executable), Path.Combine(solutionRoot, "dev-test", "app-1.0.0-dev", executable),
Path.Combine(AppContext.BaseDirectory, "..", "LanMountainDesktop", "bin", "Release", "net10.0", executable),
// dev-test 鐩綍
Path.Combine(AppContext.BaseDirectory, "..", "dev-test", "app-1.0.0-dev", executable),
}; };
foreach (var path in possiblePaths.Select(Path.GetFullPath).Distinct()) foreach (var path in possiblePaths.Select(Path.GetFullPath).Distinct())
{ {
Logger.Info($"Scanning development path: {path}");
if (File.Exists(path)) if (File.Exists(path))
{ {
Logger.Info($"Found host at: {path}");
return path; return path;
} }
} }
return null; return null;
} }
/// <summary> /// <summary>
/// 鑾峰彇寮€鍙戠幆澧冨彲鑳界殑涓荤▼搴忚矾寰? /// </summary> /// 鑾峰彇寮€鍙戞ā寮忥細鏌ユ壘涓荤▼搴忚経
/// </summary>
private static IEnumerable<string> GetDevelopmentPaths(string executable) private static IEnumerable<string> GetDevelopmentPaths(string executable)
{ {
var launcherDir = AppContext.BaseDirectory; var launcherDir = AppContext.BaseDirectory;
// 计算解决方案根目录:从 LanMountainDesktop.Launcher\bin\Debug\net10.0\ 向上4级
var solutionRoot = Path.GetFullPath(Path.Combine(launcherDir, "..", "..", "..", ".."));
var possiblePaths = new[] var possiblePaths = new[]
{ {
// 浠?Launcher 椤圭洰杩愯锛?.\LanMountainDesktop\bin\Debug\net10.0\LanMountainDesktop.exe // 标准开发路径:解决方案根目录下的 LanMountainDesktop 项目
Path.Combine(solutionRoot, "LanMountainDesktop", "bin", "Debug", "net10.0", executable),
Path.Combine(solutionRoot, "LanMountainDesktop", "bin", "Release", "net10.0", executable),
// 向后兼容:如果 Launcher 在特殊目录结构中
Path.Combine(launcherDir, "..", "..", "LanMountainDesktop", "bin", "Debug", "net10.0", executable), Path.Combine(launcherDir, "..", "..", "LanMountainDesktop", "bin", "Debug", "net10.0", executable),
Path.Combine(launcherDir, "..", "..", "LanMountainDesktop", "bin", "Release", "net10.0", executable), Path.Combine(launcherDir, "..", "..", "LanMountainDesktop", "bin", "Release", "net10.0", executable),
// 浠庤В鍐虫柟妗堟牴鐩綍杩愯锛歀anMountainDesktop\bin\Debug\net10.0\LanMountainDesktop.exe // dev-test 目录
Path.Combine(launcherDir, "..", "LanMountainDesktop", "bin", "Debug", "net10.0", executable), Path.Combine(solutionRoot, "dev-test", "app-1.0.0-dev", executable),
Path.Combine(launcherDir, "..", "LanMountainDesktop", "bin", "Release", "net10.0", executable),
// 浠?dev-test 鐩綍杩愯
Path.Combine(launcherDir, "..", "dev-test", "app-1.0.0-dev", executable),
}; };
return possiblePaths.Select(Path.GetFullPath).Distinct(); return possiblePaths.Select(Path.GetFullPath).Distinct();
} }

View File

@@ -955,7 +955,7 @@ internal sealed class LauncherFlowCoordinator
{ {
try try
{ {
await splashWindow.DismissAsync().ConfigureAwait(false); await Dispatcher.UIThread.InvokeAsync(() => splashWindow.DismissAsync());
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@@ -79,6 +79,14 @@ public partial class SplashWindow : Window, ISplashStageReporter
} }
_dismissed = true; _dismissed = true;
// 确保在UI线程上执行
if (!Dispatcher.UIThread.CheckAccess())
{
await Dispatcher.UIThread.InvokeAsync(async () => await DismissAsync());
return;
}
ConfigureForVisualMode(); ConfigureForVisualMode();
if (_mode == StartupVisualMode.SlideSplash) if (_mode == StartupVisualMode.SlideSplash)
@@ -91,13 +99,7 @@ public partial class SplashWindow : Window, ISplashStageReporter
await AnimateOpacityAsync(Opacity, 0d, FadeAnimationDuration).ConfigureAwait(false); await AnimateOpacityAsync(Opacity, 0d, FadeAnimationDuration).ConfigureAwait(false);
} }
await Dispatcher.UIThread.InvokeAsync(() => Close();
{
if (IsVisible)
{
Close();
}
});
} }
public void Report(string stage, string message) public void Report(string stage, string message)