Add dev/debug startup flow and launch profiles

Handle design-time initialization and add a developer debug startup path: App now skips normal startup when in design mode and shows a DevDebugWindow when running in debug (unless a preview or apply-update command). CommandContext.IsDebugMode is extended to include DOTNET_ENVIRONMENT=Development via a new IsDevelopmentEnvironment helper. Program.Main and BuildAvaloniaApp are made public to aid tooling. Added multiple launchSettings profiles for debug and preview commands that set DOTNET_ENVIRONMENT=Development to simplify IDE debugging and UI previewing.
This commit is contained in:
lincube
2026-04-24 17:25:53 +08:00
parent ad3648a0b8
commit 403cf280bb
4 changed files with 91 additions and 5 deletions

View File

@@ -18,6 +18,12 @@ public partial class App : Application
{ {
public override void Initialize() public override void Initialize()
{ {
if (Design.IsDesignMode)
{
AvaloniaXamlLoader.Load(this);
return;
}
Logger.Initialize(); Logger.Initialize();
var context = LauncherRuntimeContext.Current; var context = LauncherRuntimeContext.Current;
var execution = LauncherExecutionContext.Capture(); var execution = LauncherExecutionContext.Capture();
@@ -32,6 +38,12 @@ public partial class App : Application
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()
{ {
if (Design.IsDesignMode)
{
base.OnFrameworkInitializationCompleted();
return;
}
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown; desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
@@ -49,6 +61,18 @@ public partial class App : Application
return; return;
} }
// 调试模式:只显示 DevDebugWindow不走正常启动流程
// 避免启动主程序后 Launcher 自动退出,导致开发者无法预览 UI
if (context.IsDebugMode && !context.IsPreviewCommand &&
!string.Equals(context.Command, "apply-update", StringComparison.OrdinalIgnoreCase))
{
Logger.Info("Debug mode active — showing DevDebugWindow instead of normal launch flow.");
var devDebugWindow = new DevDebugWindow();
devDebugWindow.Show();
base.OnFrameworkInitializationCompleted();
return;
}
if (string.Equals(context.Command, "apply-update", StringComparison.OrdinalIgnoreCase)) if (string.Equals(context.Command, "apply-update", StringComparison.OrdinalIgnoreCase))
{ {
var updateWindow = new UpdateWindow(); var updateWindow = new UpdateWindow();

View File

@@ -37,11 +37,25 @@ internal sealed class CommandContext
/// <summary> /// <summary>
/// 是否处于调试模式(从 Rider/VS 等 IDE 启动) /// 是否处于调试模式(从 Rider/VS 等 IDE 启动)
/// 仅当明确指定 --debug 参数或调试器附加时才启用 /// 当满足以下任一条件时启用
/// 1. 明确指定 --debug 参数
/// 2. 调试器附加Debugger.IsAttached
/// 3. DOTNET_ENVIRONMENT 环境变量为 DevelopmentIDE 调试启动时自动设置)
/// </summary> /// </summary>
public bool IsDebugMode => public bool IsDebugMode =>
Options.ContainsKey("debug") || Options.ContainsKey("debug") ||
System.Diagnostics.Debugger.IsAttached; System.Diagnostics.Debugger.IsAttached ||
IsDevelopmentEnvironment;
/// <summary>
/// 是否为 Development 环境DOTNET_ENVIRONMENT=Development
/// Rider/VS 调试启动时会自动设置此环境变量
/// </summary>
public bool IsDevelopmentEnvironment =>
string.Equals(
System.Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT"),
"Development",
StringComparison.OrdinalIgnoreCase);
public bool IsPreviewCommand => public bool IsPreviewCommand =>
Command.StartsWith("preview-", StringComparison.OrdinalIgnoreCase); Command.StartsWith("preview-", StringComparison.OrdinalIgnoreCase);

View File

@@ -4,10 +4,10 @@ using LanMountainDesktop.Launcher.Services;
namespace LanMountainDesktop.Launcher; namespace LanMountainDesktop.Launcher;
internal static class Program public static class Program
{ {
[STAThread] [STAThread]
private static async Task<int> Main(string[] args) public static async Task<int> Main(string[] args)
{ {
var commandContext = CommandContext.FromArgs(args); var commandContext = CommandContext.FromArgs(args);
var execution = LauncherExecutionContext.Capture(); var execution = LauncherExecutionContext.Capture();
@@ -66,7 +66,7 @@ internal static class Program
} }
} }
private static AppBuilder BuildAvaloniaApp() public static AppBuilder BuildAvaloniaApp()
{ {
return AppBuilder.Configure<App>() return AppBuilder.Configure<App>()
.UsePlatformDetect() .UsePlatformDetect()

View File

@@ -1,6 +1,14 @@
{ {
"$schema": "http://json.schemastore.org/launchsettings.json", "$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": { "profiles": {
"Launcher (Debug Mode)": {
"commandName": "Project",
"commandLineArgs": "launch --debug",
"workingDirectory": "$(SolutionDir)",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Launcher (Launch Mode)": { "Launcher (Launch Mode)": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "launch", "commandLineArgs": "launch",
@@ -9,6 +17,46 @@
"DOTNET_ENVIRONMENT": "Development" "DOTNET_ENVIRONMENT": "Development"
} }
}, },
"Launcher (Preview Debug Window)": {
"commandName": "Project",
"commandLineArgs": "preview-debug",
"workingDirectory": "$(SolutionDir)",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Launcher (Preview Splash)": {
"commandName": "Project",
"commandLineArgs": "preview-splash",
"workingDirectory": "$(SolutionDir)",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Launcher (Preview Error)": {
"commandName": "Project",
"commandLineArgs": "preview-error",
"workingDirectory": "$(SolutionDir)",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Launcher (Preview Update)": {
"commandName": "Project",
"commandLineArgs": "preview-update",
"workingDirectory": "$(SolutionDir)",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Launcher (Preview OOBE)": {
"commandName": "Project",
"commandLineArgs": "preview-oobe",
"workingDirectory": "$(SolutionDir)",
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
},
"Launcher (Update Check)": { "Launcher (Update Check)": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "update check", "commandLineArgs": "update check",