diff --git a/XAML_COMPILER_BUG.md b/XAML_COMPILER_BUG.md new file mode 100644 index 0000000..faa0440 --- /dev/null +++ b/XAML_COMPILER_BUG.md @@ -0,0 +1,78 @@ +# WinUI 3 XAML Compiler Bug Report: Silent Crash on Type Mismatch + +## Summary + +The WinUI 3 XAML compiler (`XamlCompiler.exe`) crashes with **exit code 1 and produces no error message** when the XAML root element type doesn't match the code-behind base class. This creates a frustrating debugging experience as developers receive no indication of what's wrong. + +## Reproduction + +**Minimal repro:** `D:\github\XamlCompilerCrashRepro.zip` (6 files, ~2KB) + +### Steps +1. Create a WinUI 3 project with WinUIEx package +2. Create `MainWindow.xaml` using `` as root: + ```xml + + ``` +3. Create `MainWindow.xaml.cs` inheriting from `WindowEx`: + ```csharp + public sealed partial class MainWindow : WindowEx { ... } + ``` +4. Run `dotnet build` + +### Expected +Clear error message like: *"Type mismatch: XAML root element 'Window' doesn't match code-behind base class 'WinUIEx.WindowEx'"* + +### Actual +``` +error MSB3073: The command "XamlCompiler.exe input.json output.json" exited with code 1. +``` +No `output.json` file is created. No additional error details. + +## Environment + +| Component | Version | +|-----------|---------| +| Windows App SDK | 1.6.250602001 (also 1.8.x) | +| WinUIEx | 2.5.0+ | +| .NET | 9.0 | +| OS | Windows 11 (ARM64 and x64) | + +## Workaround + +Ensure XAML and code-behind types match: + +**Option A:** Both use `Window` +```xml + +``` +```csharp +public partial class MainWindow : Window +``` + +**Option B:** Both use `WindowEx` +```xml + +``` +```csharp +public partial class MainWindow : WindowEx +``` + +## Impact + +- **Severity:** Medium-High (blocks development, wastes debugging time) +- **Discoverability:** Very poor (no error message) +- **Affected scenarios:** Any derived Window type (WindowEx, custom base classes) + +## Related Issues + +This may be related to existing XAML compiler issues around error reporting: +- microsoft/microsoft-ui-xaml#10027 +- microsoft/microsoft-ui-xaml#9813 + +## Suggested Fix + +The XAML compiler should: +1. Detect when the partial class base type differs from the XAML root element +2. Produce a clear error message with file/line information +3. Write error details to `output.json` even on failure diff --git a/input.json.bak b/input.json.bak new file mode 100644 index 0000000..d10f17a --- /dev/null +++ b/input.json.bak @@ -0,0 +1 @@ +{"ProjectPath":"D:\\github\\moltbot-windows-hub.winui-test\\src\\Moltbot.Tray.WinUI\\Moltbot.Tray.WinUI.csproj","Language":"C#","LanguageSourceExtension":".cs","OutputPath":"obj\\Debug\\net9.0-windows10.0.19041.0\\win-arm64\\","ReferenceAssemblies":[{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.CSharp.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.CSharp.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.InteractiveExperiences.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.InteractiveExperiences.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.toolkit.uwp.notifications\\7.1.3\\lib\\net5.0-windows10.0.17763\\Microsoft.Toolkit.Uwp.Notifications.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.toolkit.uwp.notifications\\7.1.3\\lib\\net5.0-windows10.0.17763\\Microsoft.Toolkit.Uwp.Notifications.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.VisualBasic.Core.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.VisualBasic.Core.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.VisualBasic.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.VisualBasic.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.web.webview2\\1.0.2651.64\\lib_manual\\net6.0-windows10.0.17763.0\\Microsoft.Web.WebView2.Core.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.web.webview2\\1.0.2651.64\\lib_manual\\net6.0-windows10.0.17763.0\\Microsoft.Web.WebView2.Core.Projection.dll","IsSystemReference":false,"IsNuGetReference":false,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.Win32.Primitives.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.Win32.Primitives.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.Win32.Registry.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\Microsoft.Win32.Registry.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.ApplicationModel.Resources.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.ApplicationModel.Resources.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.AppLifecycle.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.AppLifecycle.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.AppNotifications.Builder.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.AppNotifications.Builder.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.AppNotifications.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.AppNotifications.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.Management.Deployment.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.Management.Deployment.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.PushNotifications.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.PushNotifications.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windows.sdk.net.ref\\10.0.19041.57\\lib\\net8.0\\Microsoft.Windows.SDK.NET.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windows.sdk.net.ref\\10.0.19041.57\\lib\\net8.0\\Microsoft.Windows.SDK.NET.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.Security.AccessControl.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.Security.AccessControl.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.Storage.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.Storage.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.System.Power.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.System.Power.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.System.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.System.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.Widgets.Projection.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.Windows.Widgets.Projection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.WindowsAppRuntime.Bootstrap.Net.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.WindowsAppRuntime.Bootstrap.Net.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.WinUI.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\lib\\net6.0-windows10.0.18362.0\\Microsoft.WinUI.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"D:\\github\\moltbot-windows-hub.winui-test\\src\\Moltbot.Shared\\bin\\Debug\\net9.0\\Moltbot.Shared.dll","ItemSpec":"D:\\github\\moltbot-windows-hub.winui-test\\src\\Moltbot.Shared\\bin\\Debug\\net9.0\\Moltbot.Shared.dll","IsSystemReference":false,"IsNuGetReference":false,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\mscorlib.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\mscorlib.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\netstandard.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\netstandard.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\octokit\\14.0.0\\lib\\netstandard2.0\\Octokit.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\octokit\\14.0.0\\lib\\netstandard2.0\\Octokit.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.AppContext.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.AppContext.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Buffers.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Buffers.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.Concurrent.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.Concurrent.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.Immutable.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.Immutable.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.NonGeneric.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.NonGeneric.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.Specialized.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Collections.Specialized.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.Annotations.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.Annotations.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.DataAnnotations.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.DataAnnotations.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.EventBasedAsync.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.EventBasedAsync.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.Primitives.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.Primitives.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.TypeConverter.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ComponentModel.TypeConverter.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Configuration.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Configuration.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Console.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Console.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Core.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Core.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Data.Common.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Data.Common.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Data.DataSetExtensions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Data.DataSetExtensions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Data.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Data.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Contracts.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Contracts.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Debug.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Debug.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.DiagnosticSource.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.DiagnosticSource.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.FileVersionInfo.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.FileVersionInfo.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Process.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Process.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.StackTrace.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.StackTrace.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.TextWriterTraceListener.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.TextWriterTraceListener.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Tools.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Tools.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.TraceSource.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.TraceSource.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Tracing.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Diagnostics.Tracing.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\system.drawing.common\\4.7.0\\ref\\netcoreapp3.0\\System.Drawing.Common.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\system.drawing.common\\4.7.0\\ref\\netcoreapp3.0\\System.Drawing.Common.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Drawing.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Drawing.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Drawing.Primitives.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Drawing.Primitives.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Dynamic.Runtime.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Dynamic.Runtime.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Formats.Asn1.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Formats.Asn1.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Formats.Tar.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Formats.Tar.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Globalization.Calendars.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Globalization.Calendars.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Globalization.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Globalization.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Globalization.Extensions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Globalization.Extensions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Compression.Brotli.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Compression.Brotli.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Compression.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Compression.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Compression.FileSystem.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Compression.FileSystem.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Compression.ZipFile.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Compression.ZipFile.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.AccessControl.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.AccessControl.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.DriveInfo.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.DriveInfo.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.Primitives.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.Primitives.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.Watcher.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.FileSystem.Watcher.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.IsolatedStorage.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.IsolatedStorage.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.MemoryMappedFiles.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.MemoryMappedFiles.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Pipelines.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Pipelines.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Pipes.AccessControl.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Pipes.AccessControl.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Pipes.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.Pipes.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.UnmanagedMemoryStream.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.IO.UnmanagedMemoryStream.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Linq.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Linq.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Linq.Expressions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Linq.Expressions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Linq.Parallel.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Linq.Parallel.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Linq.Queryable.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Linq.Queryable.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Memory.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Memory.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Http.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Http.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Http.Json.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Http.Json.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.HttpListener.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.HttpListener.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Mail.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Mail.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.NameResolution.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.NameResolution.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.NetworkInformation.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.NetworkInformation.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Ping.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Ping.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Primitives.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Primitives.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Quic.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Quic.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Requests.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Requests.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Security.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Security.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.ServicePoint.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.ServicePoint.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Sockets.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.Sockets.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebClient.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebClient.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebHeaderCollection.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebHeaderCollection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebProxy.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebProxy.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebSockets.Client.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebSockets.Client.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebSockets.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Net.WebSockets.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Numerics.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Numerics.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Numerics.Vectors.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Numerics.Vectors.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ObjectModel.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ObjectModel.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.DispatchProxy.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.DispatchProxy.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Emit.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Emit.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Emit.ILGeneration.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Emit.ILGeneration.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Emit.Lightweight.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Emit.Lightweight.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Extensions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Extensions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Metadata.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Metadata.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Primitives.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.Primitives.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.TypeExtensions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Reflection.TypeExtensions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Resources.Reader.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Resources.Reader.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Resources.ResourceManager.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Resources.ResourceManager.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Resources.Writer.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Resources.Writer.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.CompilerServices.Unsafe.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.CompilerServices.Unsafe.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.CompilerServices.VisualC.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.CompilerServices.VisualC.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Extensions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Extensions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Handles.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Handles.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.InteropServices.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.InteropServices.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.InteropServices.JavaScript.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.InteropServices.JavaScript.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.InteropServices.RuntimeInformation.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.InteropServices.RuntimeInformation.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Intrinsics.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Intrinsics.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Loader.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Loader.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Numerics.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Numerics.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.Formatters.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.Formatters.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.Json.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.Json.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.Primitives.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.Primitives.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.Xml.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Runtime.Serialization.Xml.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.AccessControl.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.AccessControl.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Claims.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Claims.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Algorithms.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Algorithms.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Cng.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Cng.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Csp.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Csp.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Encoding.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Encoding.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.OpenSsl.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.OpenSsl.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Primitives.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.Primitives.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.X509Certificates.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Cryptography.X509Certificates.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Principal.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Principal.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Principal.Windows.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.Principal.Windows.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.SecureString.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Security.SecureString.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ServiceModel.Web.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ServiceModel.Web.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ServiceProcess.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ServiceProcess.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Encoding.CodePages.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Encoding.CodePages.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Encoding.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Encoding.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Encoding.Extensions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Encoding.Extensions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Encodings.Web.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Encodings.Web.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Json.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.Json.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.RegularExpressions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Text.RegularExpressions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Channels.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Channels.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Overlapped.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Overlapped.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Tasks.Dataflow.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Tasks.Dataflow.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Tasks.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Tasks.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Tasks.Extensions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Tasks.Extensions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Tasks.Parallel.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Tasks.Parallel.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Thread.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Thread.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.ThreadPool.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.ThreadPool.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Timer.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Threading.Timer.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Transactions.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Transactions.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Transactions.Local.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Transactions.Local.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ValueTuple.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.ValueTuple.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Web.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Web.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Web.HttpUtility.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Web.HttpUtility.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Windows.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Windows.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.Linq.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.Linq.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.ReaderWriter.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.ReaderWriter.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.Serialization.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.Serialization.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XDocument.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XDocument.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XmlDocument.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XmlDocument.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XmlSerializer.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XmlSerializer.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XPath.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XPath.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XPath.XDocument.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\System.Xml.XPath.XDocument.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\updatum\\1.3.4\\lib\\net9.0\\Updatum.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\updatum\\1.3.4\\lib\\net9.0\\Updatum.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\WindowsBase.dll","ItemSpec":"C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\9.0.12\\ref\\net9.0\\WindowsBase.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windows.sdk.net.ref\\10.0.19041.57\\lib\\net8.0\\WinRT.Runtime.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windows.sdk.net.ref\\10.0.19041.57\\lib\\net8.0\\WinRT.Runtime.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"C:\\Users\\scottha\\.nuget\\packages\\winuiex\\2.5.0\\lib\\net6.0-windows10.0.19041\\WinUIEx.dll","ItemSpec":"C:\\Users\\scottha\\.nuget\\packages\\winuiex\\2.5.0\\lib\\net6.0-windows10.0.19041\\WinUIEx.dll","IsSystemReference":false,"IsNuGetReference":true,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""}],"TargetPlatformMinVersion":"10.0.19041.0","ReferenceAssemblyPaths":[],"BuildConfiguration":null,"ForceSharedStateShutdown":false,"DisableXbfGeneration":false,"DisableXbfLineInfo":false,"EnableXBindDiagnostics":false,"ClIncludeFiles":null,"CIncludeDirectories":null,"XamlApplications":[{"DependentUpon":"","FullPath":"D:\\github\\moltbot-windows-hub.winui-test\\src\\Moltbot.Tray.WinUI\\App.xaml","ItemSpec":"App.xaml","IsSystemReference":false,"IsNuGetReference":false,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""}],"XamlPages":[{"DependentUpon":"","FullPath":"D:\\github\\moltbot-windows-hub.winui-test\\src\\Moltbot.Tray.WinUI\\Windows\\NotificationHistoryWindow.xaml","ItemSpec":"Windows\\NotificationHistoryWindow.xaml","IsSystemReference":false,"IsNuGetReference":false,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"D:\\github\\moltbot-windows-hub.winui-test\\src\\Moltbot.Tray.WinUI\\Windows\\SettingsWindow.xaml","ItemSpec":"Windows\\SettingsWindow.xaml","IsSystemReference":false,"IsNuGetReference":false,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"D:\\github\\moltbot-windows-hub.winui-test\\src\\Moltbot.Tray.WinUI\\Windows\\StatusDetailWindow.xaml","ItemSpec":"Windows\\StatusDetailWindow.xaml","IsSystemReference":false,"IsNuGetReference":false,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""},{"DependentUpon":"","FullPath":"D:\\github\\moltbot-windows-hub.winui-test\\src\\Moltbot.Tray.WinUI\\Windows\\WebChatWindow.xaml","ItemSpec":"Windows\\WebChatWindow.xaml","IsSystemReference":false,"IsNuGetReference":false,"IsStaticLibraryReference":false,"MSBuild_Link":"","MSBuild_TargetPath":"","MSBuild_XamlResourceMapName":"","MSBuild_XamlComponentResourceLocation":""}],"LocalAssembly":null,"SdkXamlPages":null,"ProjectName":"Moltbot.Tray.WinUI","IsPass1":true,"RootNamespace":"MoltbotTray","OutputType":"WinExe","PriIndexName":null,"CodeGenerationControlFlags":null,"FeatureControlFlags":"EnableXBindDiagnostics;EnableDefaultValidationContextGeneration;EnableWin32Codegen;UsingCSWinRT","XAMLFingerprint":true,"UseVCMetaManaged":true,"FingerprintIgnorePaths":["C:\\Program Files (x86)\\Windows Kits\\10\\"],"VCInstallDir":null,"VCInstallPath32":null,"VCInstallPath64":null,"WindowsSdkPath":"C:\\Program Files (x86)\\Windows Kits\\10\\","CompileMode":"RealBuildPass1","SavedStateFile":"obj\\Debug\\net9.0-windows10.0.19041.0\\win-arm64\\\\XamlSaveStateFile.xml","RootsLog":null,"SuppressWarnings":null,"GenXbfPath":"C:\\Users\\scottha\\.nuget\\packages\\microsoft.windowsappsdk\\1.6.250108002\\buildTransitive\\..\\tools\\net6.0\\..\\","PrecompiledHeaderFile":null,"XamlResourceMapName":null,"XamlComponentResourceLocation":null,"XamlPlatform":null,"TargetFileName":null,"IgnoreSpecifiedTargetPlatformMinVersion":false} \ No newline at end of file diff --git a/moltbot-windows-hub.slnx b/moltbot-windows-hub.slnx index a98cf65..fd6a737 100644 --- a/moltbot-windows-hub.slnx +++ b/moltbot-windows-hub.slnx @@ -5,5 +5,6 @@ + diff --git a/src/Moltbot.Shared/Moltbot.Shared.csproj b/src/Moltbot.Shared/Moltbot.Shared.csproj index a3748ce..750e32c 100644 --- a/src/Moltbot.Shared/Moltbot.Shared.csproj +++ b/src/Moltbot.Shared/Moltbot.Shared.csproj @@ -1,7 +1,7 @@ - net10.0 + net9.0;net10.0 enable enable Moltbot.Shared diff --git a/src/Moltbot.Tray.WinUI/App.xaml b/src/Moltbot.Tray.WinUI/App.xaml new file mode 100644 index 0000000..5373ccc --- /dev/null +++ b/src/Moltbot.Tray.WinUI/App.xaml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + diff --git a/src/Moltbot.Tray.WinUI/App.xaml.cs b/src/Moltbot.Tray.WinUI/App.xaml.cs new file mode 100644 index 0000000..c56cf09 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/App.xaml.cs @@ -0,0 +1,1089 @@ +using Microsoft.Toolkit.Uwp.Notifications; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Moltbot.Shared; +using MoltbotTray.Dialogs; +using MoltbotTray.Helpers; +using MoltbotTray.Services; +using MoltbotTray.Windows; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO.Pipes; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Updatum; +using WinUIEx; + +namespace MoltbotTray; + +public partial class App : Application +{ + private const string PipeName = "MoltbotTray-DeepLink"; + + internal static readonly UpdatumManager AppUpdater = new("shanselman", "moltbot-windows-hub") + { + FetchOnlyLatestRelease = true, + InstallUpdateSingleFileExecutableName = "Moltbot.Tray.WinUI", + }; + + private TrayIcon? _trayIcon; + private MoltbotGatewayClient? _gatewayClient; + private SettingsManager? _settings; + private GlobalHotkeyService? _globalHotkey; + private System.Timers.Timer? _healthCheckTimer; + private System.Timers.Timer? _sessionPollTimer; + private Mutex? _mutex; + private Microsoft.UI.Dispatching.DispatcherQueue? _dispatcherQueue; + private CancellationTokenSource? _deepLinkCts; + + private ConnectionStatus _currentStatus = ConnectionStatus.Disconnected; + private AgentActivity? _currentActivity; + private ChannelHealth[] _lastChannels = Array.Empty(); + private SessionInfo[] _lastSessions = Array.Empty(); + private GatewayUsageInfo? _lastUsage; + private DateTime _lastCheckTime = DateTime.Now; + + // Session-aware activity tracking + private readonly Dictionary _sessionActivities = new(); + private string? _displayedSessionKey; + private DateTime _lastSessionSwitch = DateTime.MinValue; + private static readonly TimeSpan SessionSwitchDebounce = TimeSpan.FromSeconds(3); + + // Windows (created on demand) + private SettingsWindow? _settingsWindow; + private WebChatWindow? _webChatWindow; + private StatusDetailWindow? _statusDetailWindow; + private NotificationHistoryWindow? _notificationHistoryWindow; + private TrayMenuWindow? _trayMenuWindow; + + private string[]? _startupArgs; + + public App() + { + InitializeComponent(); + } + + protected override async void OnLaunched(LaunchActivatedEventArgs args) + { + _startupArgs = Environment.GetCommandLineArgs(); + _dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); + + // Single instance check - keep mutex alive for app lifetime + _mutex = new Mutex(true, "MoltbotTray", out bool createdNew); + if (!createdNew) + { + // Forward deep link args to running instance + if (_startupArgs.Length > 1 && _startupArgs[1].StartsWith("moltbot://", StringComparison.OrdinalIgnoreCase)) + { + SendDeepLinkToRunningInstance(_startupArgs[1]); + } + Exit(); + return; + } + + // Register URI scheme on first run + DeepLinkHandler.RegisterUriScheme(); + + // Check for updates before launching + var shouldLaunch = await CheckForUpdatesAsync(); + if (!shouldLaunch) + { + Exit(); + return; + } + + // Register toast activation handler + ToastNotificationManagerCompat.OnActivated += OnToastActivated; + + // Initialize settings + _settings = new SettingsManager(); + + // First-run check + if (string.IsNullOrWhiteSpace(_settings.Token)) + { + await ShowFirstRunWelcomeAsync(); + } + + // Initialize tray icon (window-less pattern from WinUIEx) + InitializeTrayIcon(); + + // Initialize gateway client + InitializeGatewayClient(); + + // Start health check timer + StartHealthCheckTimer(); + + // Start deep link server + StartDeepLinkServer(); + + // Register global hotkey if enabled + if (_settings.GlobalHotkeyEnabled) + { + _globalHotkey = new GlobalHotkeyService(); + _globalHotkey.HotkeyPressed += OnGlobalHotkeyPressed; + _globalHotkey.Register(); + } + + // Process startup deep link + if (_startupArgs.Length > 1 && _startupArgs[1].StartsWith("moltbot://", StringComparison.OrdinalIgnoreCase)) + { + HandleDeepLink(_startupArgs[1]); + } + + Logger.Info("Application started (WinUI 3)"); + } + + private void InitializeTrayIcon() + { + var iconPath = IconHelper.GetStatusIconPath(ConnectionStatus.Disconnected); + _trayIcon = new TrayIcon(1, iconPath, "Moltbot Tray — Disconnected"); + _trayIcon.IsVisible = true; + _trayIcon.Selected += OnTrayIconSelected; + _trayIcon.ContextMenu += OnTrayContextMenu; + } + + private void OnTrayIconSelected(TrayIcon sender, TrayIconEventArgs e) + { + // Left-click: show menu (same as right-click, matching WinForms behavior) + ShowTrayMenuPopup(); + } + + private void OnTrayContextMenu(TrayIcon sender, TrayIconEventArgs e) + { + // Right-click: show menu via popup window for better multi-monitor support + ShowTrayMenuPopup(); + // Don't set e.Flyout - we're handling it ourselves + } + + private async void ShowTrayMenuPopup() + { + try + { + // Close any existing menu + if (_trayMenuWindow != null) + { + try { _trayMenuWindow.Close(); } catch { } + _trayMenuWindow = null; + } + + // Pre-fetch latest data before showing menu (fire and forget, don't wait) + if (_gatewayClient != null && _currentStatus == ConnectionStatus.Connected) + { + try + { + _ = _gatewayClient.CheckHealthAsync(); + _ = _gatewayClient.RequestSessionsAsync(); + _ = _gatewayClient.RequestUsageAsync(); + } + catch { /* ignore */ } + } + + _trayMenuWindow = new TrayMenuWindow(); + _trayMenuWindow.MenuItemClicked += OnTrayMenuItemClicked; + _trayMenuWindow.Closed += (s, e) => _trayMenuWindow = null; + + BuildTrayMenuPopup(_trayMenuWindow); + _trayMenuWindow.SizeToContent(); + _trayMenuWindow.ShowAtCursor(); + } + catch (Exception ex) + { + Logger.Error($"Failed to show tray menu: {ex.Message}"); + } + } + + private void OnTrayMenuItemClicked(object? sender, string action) + { + switch (action) + { + case "status": ShowStatusDetail(); break; + case "dashboard": OpenDashboard(); break; + case "webchat": ShowWebChat(); break; + case "quicksend": ShowQuickSend(); break; + case "history": ShowNotificationHistory(); break; + case "healthcheck": _ = RunHealthCheckAsync(); break; + case "settings": ShowSettings(); break; + case "autostart": ToggleAutoStart(); break; + case "log": OpenLogFile(); break; + case "exit": ExitApplication(); break; + default: + if (action.StartsWith("session:")) + OpenDashboard($"sessions/{action[8..]}"); + else if (action.StartsWith("channel:")) + ToggleChannel(action[8..]); + break; + } + } + + private void BuildTrayMenuPopup(TrayMenuWindow menu) + { + // Brand header + menu.AddBrandHeader("🦞", "Molty"); + menu.AddSeparator(); + + // Status + var statusIcon = _currentStatus switch + { + ConnectionStatus.Connected => "✅", + ConnectionStatus.Connecting => "🔄", + ConnectionStatus.Error => "❌", + _ => "⚪" + }; + menu.AddMenuItem($"Status: {_currentStatus}", statusIcon, "status"); + + // Activity (if any) + if (_currentActivity != null && _currentActivity.Kind != Moltbot.Shared.ActivityKind.Idle) + { + menu.AddMenuItem(_currentActivity.DisplayText, _currentActivity.Glyph, "", isEnabled: false); + } + + // Usage + if (_lastUsage != null) + { + menu.AddMenuItem(_lastUsage.DisplayText, "📊", "", isEnabled: false); + } + + // Sessions (if any) - show meaningful info like the WinForms version + if (_lastSessions.Length > 0) + { + menu.AddSeparator(); + menu.AddMenuItem($"Sessions ({_lastSessions.Length})", "💬", "dashboard:sessions"); + + foreach (var session in _lastSessions.Take(5)) + { + // Extract session type from key like "agent:main:cron:uuid" or "agent:main:subagent:uuid" + var parts = session.Key.Split(':'); + var sessionType = parts.Length >= 3 ? parts[2] : "session"; + var displayName = sessionType switch + { + "main" => "Main Agent", + "cron" => "Scheduled Task", + "subagent" => "Sub-Agent", + _ => sessionType.Length > 0 ? char.ToUpper(sessionType[0]) + sessionType[1..] : "Session" + }; + + // Add model if available + if (!string.IsNullOrEmpty(session.Model)) + displayName += $" ({session.Model})"; + else if (!string.IsNullOrEmpty(session.Channel)) + displayName += $" · {session.Channel}"; + + var icon = session.IsMain ? "⭐" : "•"; + menu.AddMenuItem(displayName, icon, $"session:{session.Key}", isEnabled: false, indent: true); + } + if (_lastSessions.Length > 5) + menu.AddMenuItem($"+{_lastSessions.Length - 5} more...", "", "", isEnabled: false, indent: true); + } + + // Channels (if any) + if (_lastChannels.Length > 0) + { + menu.AddSeparator(); + menu.AddHeader("📡 Channels"); + + foreach (var channel in _lastChannels) + { + var rawStatus = channel.Status?.ToLowerInvariant() ?? ""; + + // Match status logic from WinForms version + var channelIcon = rawStatus switch + { + "ok" or "connected" or "running" or "active" or "ready" => "🟢", + "stopped" or "idle" or "paused" or "configured" or "pending" => "🟡", + "error" or "disconnected" or "failed" => "🔴", + _ => "⚪" + }; + + var channelName = char.ToUpper(channel.Name[0]) + channel.Name[1..]; + menu.AddMenuItem(channelName, channelIcon, $"channel:{channel.Name}", indent: true); + } + } + + menu.AddSeparator(); + + // Actions + menu.AddMenuItem("Open Dashboard", "🌐", "dashboard"); + menu.AddMenuItem("Open Web Chat", "💬", "webchat"); + menu.AddMenuItem("Quick Send...", "📤", "quicksend"); + menu.AddMenuItem("Notification History...", "📋", "history"); + menu.AddMenuItem("Run Health Check", "🔄", "healthcheck"); + + menu.AddSeparator(); + + // Settings + menu.AddMenuItem("Settings...", "⚙️", "settings"); + var autoStartText = (_settings?.AutoStart ?? false) ? "Auto-start ✓" : "Auto-start"; + menu.AddMenuItem(autoStartText, "🚀", "autostart"); + + menu.AddSeparator(); + + menu.AddMenuItem("Open Log File", "📄", "log"); + menu.AddMenuItem("Exit", "❌", "exit"); + } + + // Keep the old MenuFlyout method for reference but it won't be used + private void BuildTrayMenu(MenuFlyout flyout) + { + // Brand header + var brandItem = new MenuFlyoutItem + { + Text = "🦞 Moltbot Tray", + IsEnabled = false + }; + flyout.Items.Add(brandItem); + flyout.Items.Add(new MenuFlyoutSeparator()); + + // Status + var statusIcon = _currentStatus switch + { + ConnectionStatus.Connected => "✅", + ConnectionStatus.Connecting => "🔄", + ConnectionStatus.Error => "❌", + _ => "⚪" + }; + var statusItem = new MenuFlyoutItem + { + Text = $"{statusIcon} Status: {_currentStatus}" + }; + statusItem.Click += (s, e) => ShowStatusDetail(); + flyout.Items.Add(statusItem); + + // Activity (if any) + if (_currentActivity != null && _currentActivity.Kind != Moltbot.Shared.ActivityKind.Idle) + { + var activityItem = new MenuFlyoutItem + { + Text = $"{_currentActivity.Glyph} {_currentActivity.DisplayText}", + IsEnabled = false + }; + flyout.Items.Add(activityItem); + } + + // Usage + if (_lastUsage != null) + { + var usageItem = new MenuFlyoutItem + { + Text = $"📊 {_lastUsage.DisplayText}", + IsEnabled = false + }; + flyout.Items.Add(usageItem); + } + + // Sessions + if (_lastSessions.Length > 0) + { + flyout.Items.Add(new MenuFlyoutSeparator()); + var sessionsHeader = new MenuFlyoutItem + { + Text = $"💬 Sessions ({_lastSessions.Length})" + }; + sessionsHeader.Click += (s, e) => OpenDashboard("sessions"); + flyout.Items.Add(sessionsHeader); + + foreach (var session in _lastSessions.Take(5)) + { + var sessionItem = new MenuFlyoutItem + { + Text = $" • {session.DisplayText}" + }; + sessionItem.Click += (s, e) => OpenDashboard($"sessions/{session.Key}"); + flyout.Items.Add(sessionItem); + } + } + + // Channels + if (_lastChannels.Length > 0) + { + flyout.Items.Add(new MenuFlyoutSeparator()); + var channelsHeader = new MenuFlyoutItem + { + Text = "📡 Channels", + IsEnabled = false + }; + flyout.Items.Add(channelsHeader); + + foreach (var channel in _lastChannels) + { + var channelIcon = channel.Status?.ToLowerInvariant() switch + { + "ok" or "connected" or "running" => "🟢", + "connecting" or "reconnecting" => "🟡", + _ => "🔴" + }; + var channelItem = new MenuFlyoutItem + { + Text = $" {channelIcon} {channel.Name}" + }; + channelItem.Click += (s, e) => ToggleChannel(channel.Name); + flyout.Items.Add(channelItem); + } + } + + flyout.Items.Add(new MenuFlyoutSeparator()); + + // Actions + var dashboardItem = new MenuFlyoutItem { Text = "🌐 Open Dashboard" }; + dashboardItem.Click += (s, e) => OpenDashboard(); + flyout.Items.Add(dashboardItem); + + var webChatItem = new MenuFlyoutItem { Text = "💬 Open Web Chat" }; + webChatItem.Click += (s, e) => ShowWebChat(); + flyout.Items.Add(webChatItem); + + var quickSendItem = new MenuFlyoutItem { Text = "📤 Quick Send..." }; + quickSendItem.Click += (s, e) => ShowQuickSend(); + flyout.Items.Add(quickSendItem); + + var historyItem = new MenuFlyoutItem { Text = "📋 Notification History..." }; + historyItem.Click += (s, e) => ShowNotificationHistory(); + flyout.Items.Add(historyItem); + + var healthCheckItem = new MenuFlyoutItem { Text = "🔄 Run Health Check" }; + healthCheckItem.Click += async (s, e) => await RunHealthCheckAsync(); + flyout.Items.Add(healthCheckItem); + + flyout.Items.Add(new MenuFlyoutSeparator()); + + // Settings + var settingsItem = new MenuFlyoutItem { Text = "⚙️ Settings..." }; + settingsItem.Click += (s, e) => ShowSettings(); + flyout.Items.Add(settingsItem); + + var autoStartItem = new ToggleMenuFlyoutItem + { + Text = "🚀 Auto-start", + IsChecked = _settings?.AutoStart ?? false + }; + autoStartItem.Click += (s, e) => ToggleAutoStart(); + flyout.Items.Add(autoStartItem); + + flyout.Items.Add(new MenuFlyoutSeparator()); + + var logItem = new MenuFlyoutItem { Text = "📄 Open Log File" }; + logItem.Click += (s, e) => OpenLogFile(); + flyout.Items.Add(logItem); + + var exitItem = new MenuFlyoutItem { Text = "❌ Exit" }; + exitItem.Click += (s, e) => ExitApplication(); + flyout.Items.Add(exitItem); + } + + #region Gateway Client + + private void InitializeGatewayClient() + { + if (_settings == null) return; + + // Unsubscribe from old client if exists + UnsubscribeGatewayEvents(); + + _gatewayClient = new MoltbotGatewayClient(_settings.GatewayUrl, _settings.Token, new AppLogger()); + _gatewayClient.StatusChanged += OnConnectionStatusChanged; + _gatewayClient.ActivityChanged += OnActivityChanged; + _gatewayClient.NotificationReceived += OnNotificationReceived; + _gatewayClient.ChannelHealthUpdated += OnChannelHealthUpdated; + _gatewayClient.SessionsUpdated += OnSessionsUpdated; + _gatewayClient.UsageUpdated += OnUsageUpdated; + _ = _gatewayClient.ConnectAsync(); + } + + private void UnsubscribeGatewayEvents() + { + if (_gatewayClient != null) + { + _gatewayClient.StatusChanged -= OnConnectionStatusChanged; + _gatewayClient.ActivityChanged -= OnActivityChanged; + _gatewayClient.NotificationReceived -= OnNotificationReceived; + _gatewayClient.ChannelHealthUpdated -= OnChannelHealthUpdated; + _gatewayClient.SessionsUpdated -= OnSessionsUpdated; + _gatewayClient.UsageUpdated -= OnUsageUpdated; + } + } + + private void OnConnectionStatusChanged(object? sender, ConnectionStatus status) + { + _currentStatus = status; + UpdateTrayIcon(); + + if (status == ConnectionStatus.Connected) + { + _ = RunHealthCheckAsync(); + } + } + + private void OnActivityChanged(object? sender, AgentActivity? activity) + { + if (activity == null) + { + // Activity ended + if (_displayedSessionKey != null && _sessionActivities.ContainsKey(_displayedSessionKey)) + { + _sessionActivities.Remove(_displayedSessionKey); + } + _currentActivity = null; + } + else + { + var sessionKey = activity.SessionKey ?? "default"; + _sessionActivities[sessionKey] = activity; + + // Debounce session switching + var now = DateTime.Now; + if (_displayedSessionKey != sessionKey && + (now - _lastSessionSwitch) > SessionSwitchDebounce) + { + _displayedSessionKey = sessionKey; + _lastSessionSwitch = now; + } + + if (_displayedSessionKey == sessionKey) + { + _currentActivity = activity; + } + } + + UpdateTrayIcon(); + } + + private void OnChannelHealthUpdated(object? sender, ChannelHealth[] channels) + { + _lastChannels = channels; + } + + private void OnSessionsUpdated(object? sender, SessionInfo[] sessions) + { + _lastSessions = sessions; + } + + private void OnUsageUpdated(object? sender, GatewayUsageInfo usage) + { + _lastUsage = usage; + } + + private void OnNotificationReceived(object? sender, MoltbotNotification notification) + { + if (_settings?.ShowNotifications != true) return; + if (!ShouldShowNotification(notification)) return; + + // Store in history + NotificationHistoryService.AddNotification(new Services.GatewayNotification + { + Title = notification.Title, + Message = notification.Message, + Category = notification.Type + }); + + // Show toast + try + { + var builder = new ToastContentBuilder() + .AddText(notification.Title ?? "Moltbot") + .AddText(notification.Message); + + builder.Show(); + } + catch (Exception ex) + { + Logger.Warn($"Failed to show toast: {ex.Message}"); + } + } + + private bool ShouldShowNotification(MoltbotNotification notification) + { + if (_settings == null) return true; + + return notification.Type?.ToLowerInvariant() switch + { + "health" => _settings.NotifyHealth, + "urgent" => _settings.NotifyUrgent, + "reminder" => _settings.NotifyReminder, + "email" => _settings.NotifyEmail, + "calendar" => _settings.NotifyCalendar, + "build" => _settings.NotifyBuild, + "stock" => _settings.NotifyStock, + "info" => _settings.NotifyInfo, + _ => true + }; + } + + #endregion + + #region Health Check + + private void StartHealthCheckTimer() + { + _healthCheckTimer = new System.Timers.Timer(30000); // 30 seconds + _healthCheckTimer.Elapsed += async (s, e) => await RunHealthCheckAsync(); + _healthCheckTimer.Start(); + + _sessionPollTimer = new System.Timers.Timer(10000); // 10 seconds + _sessionPollTimer.Elapsed += async (s, e) => await PollSessionsAsync(); + _sessionPollTimer.Start(); + + // Initial check + _ = RunHealthCheckAsync(); + } + + private async Task RunHealthCheckAsync() + { + if (_gatewayClient == null) return; + + try + { + _lastCheckTime = DateTime.Now; + await _gatewayClient.CheckHealthAsync(); + } + catch (Exception ex) + { + Logger.Warn($"Health check failed: {ex.Message}"); + } + } + + private async Task PollSessionsAsync() + { + if (_gatewayClient == null) return; + + try + { + await _gatewayClient.RequestSessionsAsync(); + await _gatewayClient.RequestUsageAsync(); + } + catch (Exception ex) + { + Logger.Warn($"Session poll failed: {ex.Message}"); + } + } + + #endregion + + #region Tray Icon + + private void UpdateTrayIcon() + { + if (_trayIcon == null) return; + + var status = _currentStatus; + if (_currentActivity != null && _currentActivity.Kind != Moltbot.Shared.ActivityKind.Idle) + { + status = ConnectionStatus.Connecting; // Use connecting icon for activity + } + + var iconPath = IconHelper.GetStatusIconPath(status); + var tooltip = $"Moltbot Tray — {_currentStatus}"; + + if (_currentActivity != null && !string.IsNullOrEmpty(_currentActivity.DisplayText)) + { + tooltip += $"\n{_currentActivity.DisplayText}"; + } + + tooltip += $"\nLast check: {_lastCheckTime:HH:mm:ss}"; + + try + { + _trayIcon.SetIcon(iconPath); + _trayIcon.Tooltip = tooltip; + } + catch (Exception ex) + { + Logger.Warn($"Failed to update tray icon: {ex.Message}"); + } + } + + #endregion + + #region Window Management + + private void ShowSettings() + { + if (_settingsWindow == null || _settingsWindow.IsClosed) + { + _settingsWindow = new SettingsWindow(_settings!); + _settingsWindow.Closed += (s, e) => + { + _settingsWindow.SettingsSaved -= OnSettingsSaved; + _settingsWindow = null; + }; + _settingsWindow.SettingsSaved += OnSettingsSaved; + } + _settingsWindow.Activate(); + } + + private void OnSettingsSaved(object? sender, EventArgs e) + { + // Reconnect with new settings + _gatewayClient?.Dispose(); + InitializeGatewayClient(); + + // Update global hotkey + if (_settings!.GlobalHotkeyEnabled) + { + _globalHotkey ??= new GlobalHotkeyService(); + _globalHotkey.HotkeyPressed -= OnGlobalHotkeyPressed; + _globalHotkey.HotkeyPressed += OnGlobalHotkeyPressed; + _globalHotkey.Register(); + } + else + { + _globalHotkey?.Unregister(); + } + + // Update auto-start + AutoStartManager.SetAutoStart(_settings.AutoStart); + } + + private void ShowWebChat() + { + if (_webChatWindow == null || _webChatWindow.IsClosed) + { + _webChatWindow = new WebChatWindow(_settings!.GatewayUrl, _settings.Token); + _webChatWindow.Closed += (s, e) => _webChatWindow = null; + } + _webChatWindow.Activate(); + } + + private void ShowQuickSend(string? prefillMessage = null) + { + if (_gatewayClient == null) return; + var dialog = new QuickSendDialog(_gatewayClient, prefillMessage); + dialog.Activate(); + } + + private void ShowStatusDetail() + { + if (_statusDetailWindow == null || _statusDetailWindow.IsClosed) + { + _statusDetailWindow = new StatusDetailWindow( + _currentStatus, _lastChannels, _lastSessions, _lastUsage, _lastCheckTime); + _statusDetailWindow.Closed += (s, e) => _statusDetailWindow = null; + } + else + { + _statusDetailWindow.UpdateStatus( + _currentStatus, _lastChannels, _lastSessions, _lastUsage, _lastCheckTime); + } + _statusDetailWindow.Activate(); + } + + private void ShowNotificationHistory() + { + if (_notificationHistoryWindow == null || _notificationHistoryWindow.IsClosed) + { + _notificationHistoryWindow = new NotificationHistoryWindow(); + _notificationHistoryWindow.Closed += (s, e) => _notificationHistoryWindow = null; + } + _notificationHistoryWindow.Activate(); + } + + private async Task ShowFirstRunWelcomeAsync() + { + var dialog = new WelcomeDialog(); + var result = await dialog.ShowAsync(); + if (result == ContentDialogResult.Primary) + { + ShowSettings(); + } + } + + #endregion + + #region Actions + + private void OpenDashboard(string? path = null) + { + if (_settings == null) return; + + var baseUrl = _settings.GatewayUrl + .Replace("ws://", "http://") + .Replace("wss://", "https://"); + + var url = string.IsNullOrEmpty(path) + ? $"{baseUrl}?token={Uri.EscapeDataString(_settings.Token)}" + : $"{baseUrl}/{path}?token={Uri.EscapeDataString(_settings.Token)}"; + + try + { + Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); + } + catch (Exception ex) + { + Logger.Error($"Failed to open dashboard: {ex.Message}"); + } + } + + private async void ToggleChannel(string channelName) + { + if (_gatewayClient == null) return; + + var channel = _lastChannels.FirstOrDefault(c => c.Name == channelName); + if (channel == null) return; + + try + { + var isRunning = channel.Status?.ToLowerInvariant() is "ok" or "connected" or "running"; + if (isRunning) + { + await _gatewayClient.StopChannelAsync(channelName); + } + else + { + await _gatewayClient.StartChannelAsync(channelName); + } + + // Refresh health + await RunHealthCheckAsync(); + } + catch (Exception ex) + { + Logger.Error($"Failed to toggle channel: {ex.Message}"); + } + } + + private void ToggleAutoStart() + { + if (_settings == null) return; + _settings.AutoStart = !_settings.AutoStart; + _settings.Save(); + AutoStartManager.SetAutoStart(_settings.AutoStart); + } + + private void OpenLogFile() + { + try + { + Process.Start(new ProcessStartInfo(Logger.LogFilePath) { UseShellExecute = true }); + } + catch (Exception ex) + { + Logger.Error($"Failed to open log file: {ex.Message}"); + } + } + + private void OnGlobalHotkeyPressed(object? sender, EventArgs e) + { + ShowQuickSend(); + } + + #endregion + + #region Updates + + private async Task CheckForUpdatesAsync() + { + try + { + Logger.Info("Checking for updates..."); + var updateFound = await AppUpdater.CheckForUpdatesAsync(); + + if (!updateFound) + { + Logger.Info("No updates available"); + return true; + } + + var release = AppUpdater.LatestRelease!; + var changelog = AppUpdater.GetChangelog(true) ?? "No release notes available."; + Logger.Info($"Update available: {release.TagName}"); + + var dialog = new UpdateDialog(release.TagName, changelog); + var result = await dialog.ShowAsync(); + + if (result == UpdateDialogResult.Download) + { + var installed = await DownloadAndInstallUpdateAsync(); + return !installed; // Don't launch if update succeeded + } + + return true; // RemindLater or Skip - continue + } + catch (Exception ex) + { + Logger.Warn($"Update check failed: {ex.Message}"); + return true; + } + } + + private async Task DownloadAndInstallUpdateAsync() + { + DownloadProgressDialog? progressDialog = null; + try + { + progressDialog = new DownloadProgressDialog(AppUpdater); + progressDialog.ShowAsync(); // Fire and forget + + var downloadedAsset = await AppUpdater.DownloadUpdateAsync(); + + progressDialog?.Close(); + + if (downloadedAsset == null || !System.IO.File.Exists(downloadedAsset.FilePath)) + { + Logger.Error("Update download failed or file missing"); + return false; + } + + Logger.Info("Installing update and restarting..."); + await AppUpdater.InstallUpdateAsync(downloadedAsset); + return true; + } + catch (Exception ex) + { + Logger.Error($"Update failed: {ex.Message}"); + progressDialog?.Close(); + return false; + } + } + + #endregion + + #region Deep Links + + private void StartDeepLinkServer() + { + _deepLinkCts = new CancellationTokenSource(); + var token = _deepLinkCts.Token; + + Task.Run(async () => + { + while (!token.IsCancellationRequested) + { + try + { + using var pipe = new NamedPipeServerStream(PipeName, PipeDirection.In); + await pipe.WaitForConnectionAsync(token); + using var reader = new System.IO.StreamReader(pipe); + var uri = await reader.ReadLineAsync(token); + if (!string.IsNullOrEmpty(uri)) + { + Logger.Info($"Received deep link via IPC: {uri}"); + _dispatcherQueue?.TryEnqueue(() => HandleDeepLink(uri)); + } + } + catch (OperationCanceledException) + { + break; // Normal shutdown + } + catch (Exception ex) + { + if (!token.IsCancellationRequested) + { + Logger.Warn($"Deep link server error: {ex.Message}"); + try { await Task.Delay(1000, token); } catch { break; } + } + } + } + }, token); + } + + private void HandleDeepLink(string uri) + { + DeepLinkHandler.Handle(uri, new DeepLinkActions + { + OpenSettings = ShowSettings, + OpenChat = ShowWebChat, + OpenDashboard = OpenDashboard, + OpenQuickSend = ShowQuickSend, + SendMessage = async (msg) => + { + if (_gatewayClient != null) + { + await _gatewayClient.SendChatMessageAsync(msg); + } + } + }); + } + + private static void SendDeepLinkToRunningInstance(string uri) + { + try + { + using var pipe = new NamedPipeClientStream(".", PipeName, PipeDirection.Out); + pipe.Connect(1000); + using var writer = new System.IO.StreamWriter(pipe); + writer.WriteLine(uri); + writer.Flush(); + } + catch (Exception ex) + { + Logger.Warn($"Failed to forward deep link: {ex.Message}"); + } + } + + #endregion + + #region Toast Activation + + private void OnToastActivated(ToastNotificationActivatedEventArgsCompat args) + { + var arguments = ToastArguments.Parse(args.Argument); + + if (arguments.TryGetValue("action", out var action)) + { + _dispatcherQueue?.TryEnqueue(() => + { + switch (action) + { + case "open_url" when arguments.TryGetValue("url", out var url): + try { Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); } + catch { } + break; + case "open_dashboard": + OpenDashboard(); + break; + case "open_settings": + ShowSettings(); + break; + } + }); + } + } + + #endregion + + #region Exit + + private void ExitApplication() + { + Logger.Info("Application exiting"); + + // Cancel background tasks + _deepLinkCts?.Cancel(); + + // Stop timers + _healthCheckTimer?.Stop(); + _healthCheckTimer?.Dispose(); + _sessionPollTimer?.Stop(); + _sessionPollTimer?.Dispose(); + + // Cleanup hotkey + _globalHotkey?.Dispose(); + + // Unsubscribe and dispose gateway client + UnsubscribeGatewayEvents(); + _gatewayClient?.Dispose(); + + // Dispose tray and mutex + _trayIcon?.Dispose(); + _mutex?.Dispose(); + + // Dispose cancellation token source + _deepLinkCts?.Dispose(); + + Exit(); + } + + #endregion + + private Microsoft.UI.Dispatching.DispatcherQueue? AppDispatcherQueue => + Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); +} + +internal class AppLogger : IMoltbotLogger +{ + public void Info(string message) => Logger.Info(message); + public void Warn(string message) => Logger.Warn(message); + public void Error(string message, Exception? ex = null) => + Logger.Error(ex != null ? $"{message}: {ex.Message}" : message); +} diff --git a/src/Moltbot.Tray.WinUI/Assets/moltbot.ico b/src/Moltbot.Tray.WinUI/Assets/moltbot.ico new file mode 100644 index 0000000..1b7300e Binary files /dev/null and b/src/Moltbot.Tray.WinUI/Assets/moltbot.ico differ diff --git a/src/Moltbot.Tray.WinUI/Dialogs/DownloadProgressDialog.cs b/src/Moltbot.Tray.WinUI/Dialogs/DownloadProgressDialog.cs new file mode 100644 index 0000000..b8de9fc --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Dialogs/DownloadProgressDialog.cs @@ -0,0 +1,33 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Updatum; + +namespace MoltbotTray.Dialogs; + +public sealed class DownloadProgressDialog +{ + private Window? _window; + private readonly UpdatumManager? _updater; + + public DownloadProgressDialog(UpdatumManager updater) + { + _updater = updater; + } + + public void ShowAsync() + { + _window = new Window { Title = "Downloading Update..." }; + + var panel = new StackPanel { Padding = new Thickness(20) }; + var progressText = new TextBlock { Text = "Downloading update...", Margin = new Thickness(0, 0, 0, 10) }; + var progressBar = new ProgressBar { IsIndeterminate = true }; + + panel.Children.Add(progressText); + panel.Children.Add(progressBar); + _window.Content = panel; + + _window.Activate(); + } + + public void Close() => _window?.Close(); +} diff --git a/src/Moltbot.Tray.WinUI/Dialogs/QuickSendDialog.cs b/src/Moltbot.Tray.WinUI/Dialogs/QuickSendDialog.cs new file mode 100644 index 0000000..4d3cb87 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Dialogs/QuickSendDialog.cs @@ -0,0 +1,139 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Input; +using Moltbot.Shared; +using MoltbotTray.Helpers; +using MoltbotTray.Services; +using System; +using System.Threading.Tasks; +using WinUIEx; + +namespace MoltbotTray.Dialogs; + +/// +/// Quick send dialog for sending messages to Moltbot. +/// +public sealed class QuickSendDialog : WindowEx +{ + private readonly MoltbotGatewayClient _client; + private readonly TextBox _messageTextBox; + private readonly Button _sendButton; + private readonly TextBlock _statusText; + private bool _isSending; + + public QuickSendDialog(MoltbotGatewayClient client, string? prefillMessage = null) + { + _client = client; + + // Window setup + Title = "Quick Send — Moltbot"; + this.SetWindowSize(400, 200); + this.CenterOnScreen(); + this.SetIcon(IconHelper.GetStatusIconPath(ConnectionStatus.Connected)); + + // Build UI programmatically (simple dialog) + var root = new StackPanel + { + Spacing = 12, + Padding = new Thickness(24) + }; + + var header = new TextBlock + { + Text = "📤 Quick Send", + Style = (Style)Application.Current.Resources["SubtitleTextBlockStyle"] + }; + root.Children.Add(header); + + _messageTextBox = new TextBox + { + PlaceholderText = "Type your message...", + AcceptsReturn = false, + Text = prefillMessage ?? "" + }; + _messageTextBox.KeyDown += OnKeyDown; + root.Children.Add(_messageTextBox); + + var buttonPanel = new StackPanel + { + Orientation = Orientation.Horizontal, + Spacing = 8, + HorizontalAlignment = HorizontalAlignment.Right + }; + + _statusText = new TextBlock + { + VerticalAlignment = VerticalAlignment.Center, + Margin = new Thickness(0, 0, 12, 0) + }; + buttonPanel.Children.Add(_statusText); + + var cancelButton = new Button { Content = "Cancel" }; + cancelButton.Click += (s, e) => Close(); + buttonPanel.Children.Add(cancelButton); + + _sendButton = new Button + { + Content = "Send", + Style = (Style)Application.Current.Resources["AccentButtonStyle"] + }; + _sendButton.Click += OnSendClick; + buttonPanel.Children.Add(_sendButton); + + root.Children.Add(buttonPanel); + + Content = root; + + // Focus the text box when shown + Activated += (s, e) => _messageTextBox.Focus(FocusState.Programmatic); + } + + private async void OnKeyDown(object sender, KeyRoutedEventArgs e) + { + if (e.Key == global::Windows.System.VirtualKey.Enter && !_isSending) + { + e.Handled = true; + await SendMessageAsync(); + } + else if (e.Key == global::Windows.System.VirtualKey.Escape) + { + Close(); + } + } + + private async void OnSendClick(object sender, RoutedEventArgs e) + { + await SendMessageAsync(); + } + + private async Task SendMessageAsync() + { + var message = _messageTextBox.Text?.Trim(); + if (string.IsNullOrEmpty(message)) return; + + _isSending = true; + _sendButton.IsEnabled = false; + _messageTextBox.IsEnabled = false; + _statusText.Text = "Sending..."; + + try + { + await _client.SendChatMessageAsync(message); + Logger.Info($"Quick send: {message}"); + Close(); + } + catch (Exception ex) + { + Logger.Error($"Quick send failed: {ex.Message}"); + _statusText.Text = "❌ Failed"; + _sendButton.IsEnabled = true; + _messageTextBox.IsEnabled = true; + _isSending = false; + } + } + + public new void ShowAsync() + { + Activate(); + } +} diff --git a/src/Moltbot.Tray.WinUI/Dialogs/UpdateDialog.cs b/src/Moltbot.Tray.WinUI/Dialogs/UpdateDialog.cs new file mode 100644 index 0000000..c6b5dcd --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Dialogs/UpdateDialog.cs @@ -0,0 +1,103 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using System; +using System.Threading.Tasks; + +namespace MoltbotTray.Dialogs; + +public enum UpdateDialogResult +{ + Download, + Skip, + RemindLater +} + +/// +/// Dialog showing available update with release notes. +/// +public sealed class UpdateDialog +{ + private readonly string _version; + private readonly string _changelog; + private ContentDialog? _dialog; + + public UpdateDialogResult Result { get; private set; } = UpdateDialogResult.RemindLater; + + public UpdateDialog(string version, string changelog) + { + _version = version; + _changelog = changelog; + } + + public async Task ShowAsync() + { + // Create a temporary window to host the dialog + var window = new Window(); + window.Content = new Grid(); + window.Activate(); + + // Build dialog content + var content = new StackPanel + { + Spacing = 16, + MaxWidth = 450 + }; + + // Version header + content.Children.Add(new TextBlock + { + Text = $"🎉 Version {_version} is available!", + Style = (Style)Application.Current.Resources["SubtitleTextBlockStyle"] + }); + + // Current version + var currentVersion = typeof(UpdateDialog).Assembly.GetName().Version?.ToString() ?? "Unknown"; + content.Children.Add(new TextBlock + { + Text = $"Current version: {currentVersion}", + Foreground = (Microsoft.UI.Xaml.Media.Brush)Application.Current.Resources["TextFillColorSecondaryBrush"] + }); + + // Changelog + content.Children.Add(new TextBlock + { + Text = "What's New:", + FontWeight = Microsoft.UI.Text.FontWeights.SemiBold + }); + + var changelogScroll = new ScrollViewer + { + MaxHeight = 200, + Content = new TextBlock + { + Text = _changelog, + TextWrapping = TextWrapping.Wrap + } + }; + content.Children.Add(changelogScroll); + + // Create dialog + _dialog = new ContentDialog + { + Title = "Update Available", + Content = content, + PrimaryButtonText = "Download & Install", + SecondaryButtonText = "Remind Me Later", + CloseButtonText = "Skip This Version", + DefaultButton = ContentDialogButton.Primary, + XamlRoot = window.Content.XamlRoot + }; + + var dialogResult = await _dialog.ShowAsync(); + window.Close(); + + Result = dialogResult switch + { + ContentDialogResult.Primary => UpdateDialogResult.Download, + ContentDialogResult.Secondary => UpdateDialogResult.RemindLater, + _ => UpdateDialogResult.Skip + }; + + return Result; + } +} diff --git a/src/Moltbot.Tray.WinUI/Dialogs/WelcomeDialog.cs b/src/Moltbot.Tray.WinUI/Dialogs/WelcomeDialog.cs new file mode 100644 index 0000000..00b97c9 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Dialogs/WelcomeDialog.cs @@ -0,0 +1,128 @@ +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using System; +using System.Threading.Tasks; +using WinUIEx; + +namespace MoltbotTray.Dialogs; + +/// +/// First-run welcome dialog for new users. +/// +public sealed class WelcomeDialog : WindowEx +{ + private readonly TaskCompletionSource _tcs = new(); + private ContentDialogResult _result = ContentDialogResult.None; + + public WelcomeDialog() + { + Title = "Welcome to Moltbot"; + this.SetWindowSize(480, 440); + this.CenterOnScreen(); + this.SetIcon("Assets\\moltbot.ico"); + + // Build UI directly in the window (no ContentDialog needed) + var root = new Grid + { + Padding = new Thickness(32), + RowSpacing = 16 + }; + root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + root.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) }); + root.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + // Lobster header + var headerPanel = new StackPanel + { + Orientation = Orientation.Horizontal, + Spacing = 12, + HorizontalAlignment = HorizontalAlignment.Center + }; + headerPanel.Children.Add(new TextBlock + { + Text = "🦞", + FontSize = 48 + }); + headerPanel.Children.Add(new TextBlock + { + Text = "Welcome to Moltbot!", + Style = (Style)Application.Current.Resources["TitleTextBlockStyle"], + VerticalAlignment = VerticalAlignment.Center + }); + Grid.SetRow(headerPanel, 0); + root.Children.Add(headerPanel); + + // Content + var content = new StackPanel { Spacing = 16 }; + + content.Children.Add(new TextBlock + { + Text = "Moltbot Tray is your Windows companion for Moltbot, the AI-powered personal assistant.", + TextWrapping = TextWrapping.Wrap + }); + + var gettingStarted = new StackPanel { Spacing = 8 }; + gettingStarted.Children.Add(new TextBlock + { + Text = "To get started, you'll need:", + FontWeight = Microsoft.UI.Text.FontWeights.SemiBold + }); + + var bulletList = new StackPanel { Spacing = 4, Margin = new Thickness(16, 0, 0, 0) }; + bulletList.Children.Add(new TextBlock { Text = "• A running Moltbot gateway" }); + bulletList.Children.Add(new TextBlock { Text = "• Your API token from the dashboard" }); + gettingStarted.Children.Add(bulletList); + content.Children.Add(gettingStarted); + + var docsButton = new HyperlinkButton + { + Content = "📚 View Documentation", + NavigateUri = new Uri("https://docs.molt.bot/web/dashboard") + }; + content.Children.Add(docsButton); + + Grid.SetRow(content, 1); + root.Children.Add(content); + + // Buttons + var buttonPanel = new StackPanel + { + Orientation = Orientation.Horizontal, + HorizontalAlignment = HorizontalAlignment.Right, + Spacing = 8 + }; + + var laterButton = new Button { Content = "Later" }; + laterButton.Click += (s, e) => + { + _result = ContentDialogResult.None; + Close(); + }; + buttonPanel.Children.Add(laterButton); + + var settingsButton = new Button + { + Content = "Open Settings", + Style = (Style)Application.Current.Resources["AccentButtonStyle"] + }; + settingsButton.Click += (s, e) => + { + _result = ContentDialogResult.Primary; + Close(); + }; + buttonPanel.Children.Add(settingsButton); + + Grid.SetRow(buttonPanel, 2); + root.Children.Add(buttonPanel); + + Content = root; + + Closed += (s, e) => _tcs.TrySetResult(_result); + } + + public new Task ShowAsync() + { + Activate(); + return _tcs.Task; + } +} diff --git a/src/Moltbot.Tray.WinUI/Helpers/IconHelper.cs b/src/Moltbot.Tray.WinUI/Helpers/IconHelper.cs new file mode 100644 index 0000000..f77e4aa --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Helpers/IconHelper.cs @@ -0,0 +1,145 @@ +using Moltbot.Shared; +using System; +using System.Drawing; +using System.IO; +using System.Runtime.InteropServices; + +namespace MoltbotTray.Helpers; + +/// +/// Provides icon resources for the tray application. +/// Creates dynamic status icons with lobster pixel art. +/// +public static class IconHelper +{ + private static readonly string AssetsPath = Path.Combine(AppContext.BaseDirectory, "Assets"); + private static readonly string IconsPath = Path.Combine(AssetsPath, "Icons"); + + // Icon cache + private static Icon? _connectedIcon; + private static Icon? _disconnectedIcon; + private static Icon? _activityIcon; + private static Icon? _errorIcon; + private static Icon? _appIcon; + + public static string GetStatusIconPath(ConnectionStatus status) + { + var iconName = status switch + { + ConnectionStatus.Connected => "StatusConnected.ico", + ConnectionStatus.Connecting => "StatusConnecting.ico", + ConnectionStatus.Error => "StatusError.ico", + _ => "StatusDisconnected.ico" + }; + + var path = Path.Combine(IconsPath, iconName); + + // If specific icon doesn't exist, fall back to main icon + if (!File.Exists(path)) + { + path = Path.Combine(AssetsPath, "moltbot.ico"); + } + + return path; + } + + public static Icon GetStatusIcon(ConnectionStatus status) + { + return status switch + { + ConnectionStatus.Connected => GetOrCreateIcon(ref _connectedIcon, ConnectionStatus.Connected), + ConnectionStatus.Connecting => GetOrCreateIcon(ref _activityIcon, ConnectionStatus.Connecting), + ConnectionStatus.Error => GetOrCreateIcon(ref _errorIcon, ConnectionStatus.Error), + _ => GetOrCreateIcon(ref _disconnectedIcon, ConnectionStatus.Disconnected) + }; + } + + public static Icon GetAppIcon() + { + if (_appIcon != null) return _appIcon; + + var iconPath = Path.Combine(AssetsPath, "moltbot.ico"); + if (File.Exists(iconPath)) + { + _appIcon = new Icon(iconPath); + } + else + { + _appIcon = CreateLobsterIcon(Color.FromArgb(255, 99, 71)); // Lobster red + } + + return _appIcon; + } + + private static Icon GetOrCreateIcon(ref Icon? cached, ConnectionStatus status) + { + if (cached != null) return cached; + + var iconPath = GetStatusIconPath(status); + if (File.Exists(iconPath)) + { + cached = new Icon(iconPath); + } + else + { + // Generate dynamic icon + var color = status switch + { + ConnectionStatus.Connected => Color.FromArgb(76, 175, 80), // Green + ConnectionStatus.Connecting => Color.FromArgb(255, 193, 7), // Amber + ConnectionStatus.Error => Color.FromArgb(244, 67, 54), // Red + _ => Color.FromArgb(158, 158, 158) // Gray + }; + cached = CreateLobsterIcon(color); + } + + return cached; + } + + /// + /// Creates a simple colored lobster icon programmatically. + /// Uses pixel art style matching the original WinForms version. + /// + public static Icon CreateLobsterIcon(Color color) + { + const int size = 16; + using var bitmap = new Bitmap(size, size); + using var g = Graphics.FromImage(bitmap); + + g.Clear(Color.Transparent); + + // Simple lobster silhouette (pixel art style) + using var brush = new SolidBrush(color); + + // Body + g.FillRectangle(brush, 6, 6, 4, 6); + + // Claws + g.FillRectangle(brush, 3, 4, 2, 2); + g.FillRectangle(brush, 11, 4, 2, 2); + g.FillRectangle(brush, 4, 6, 2, 2); + g.FillRectangle(brush, 10, 6, 2, 2); + + // Tail + g.FillRectangle(brush, 7, 12, 2, 3); + g.FillRectangle(brush, 5, 14, 6, 1); + + // Eyes + using var eyeBrush = new SolidBrush(Color.White); + g.FillRectangle(eyeBrush, 6, 5, 1, 1); + g.FillRectangle(eyeBrush, 9, 5, 1, 1); + + // Convert bitmap to icon + var hIcon = bitmap.GetHicon(); + var icon = Icon.FromHandle(hIcon); + + // Clone to own the icon data + var result = (Icon)icon.Clone(); + DestroyIcon(hIcon); + + return result; + } + + [DllImport("user32.dll", CharSet = CharSet.Auto)] + private static extern bool DestroyIcon(IntPtr handle); +} diff --git a/src/Moltbot.Tray.WinUI/Helpers/ThemeHelper.cs b/src/Moltbot.Tray.WinUI/Helpers/ThemeHelper.cs new file mode 100644 index 0000000..f1e0215 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Helpers/ThemeHelper.cs @@ -0,0 +1,57 @@ +using Microsoft.UI.Xaml; +using Microsoft.Win32; +using Windows.UI; + +namespace MoltbotTray.Helpers; + +/// +/// Helpers for detecting and applying Windows theme (dark/light mode). +/// +public static class ThemeHelper +{ + public static bool IsDarkMode() + { + try + { + using var key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"); + var value = key?.GetValue("AppsUseLightTheme"); + return value is int i && i == 0; + } + catch + { + return false; + } + } + + public static ElementTheme GetCurrentTheme() + { + return IsDarkMode() ? ElementTheme.Dark : ElementTheme.Light; + } + + public static Color GetAccentColor() + { + // Lobster red accent + return Color.FromArgb(255, 255, 99, 71); + } + + public static Color GetBackgroundColor() + { + return IsDarkMode() + ? Color.FromArgb(255, 32, 32, 32) + : Color.FromArgb(255, 249, 249, 249); + } + + public static Color GetForegroundColor() + { + return IsDarkMode() + ? Color.FromArgb(255, 255, 255, 255) + : Color.FromArgb(255, 28, 28, 28); + } + + public static Color GetSubtleTextColor() + { + return IsDarkMode() + ? Color.FromArgb(255, 180, 180, 180) + : Color.FromArgb(255, 100, 100, 100); + } +} diff --git a/src/Moltbot.Tray.WinUI/Moltbot.Tray.WinUI.csproj b/src/Moltbot.Tray.WinUI/Moltbot.Tray.WinUI.csproj new file mode 100644 index 0000000..42da7f8 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Moltbot.Tray.WinUI.csproj @@ -0,0 +1,33 @@ + + + + WinExe + net9.0-windows10.0.19041.0 + true + enable + enable + None + true + Assets\moltbot.ico + MoltbotTray + app.manifest + + + + + + + + + + + + + + + + + + + + diff --git a/src/Moltbot.Tray.WinUI/Services/AutoStartManager.cs b/src/Moltbot.Tray.WinUI/Services/AutoStartManager.cs new file mode 100644 index 0000000..3ad411e --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Services/AutoStartManager.cs @@ -0,0 +1,51 @@ +using Microsoft.Win32; +using System; + +namespace MoltbotTray.Services; + +/// +/// Manages Windows auto-start registry entries. +/// +public static class AutoStartManager +{ + private const string RegistryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run"; + private const string AppName = "MoltbotTray"; + + public static bool IsAutoStartEnabled() + { + try + { + using var key = Registry.CurrentUser.OpenSubKey(RegistryKey, false); + return key?.GetValue(AppName) != null; + } + catch + { + return false; + } + } + + public static void SetAutoStart(bool enable) + { + try + { + using var key = Registry.CurrentUser.OpenSubKey(RegistryKey, true); + if (key == null) return; + + if (enable) + { + var exePath = Environment.ProcessPath ?? System.Reflection.Assembly.GetExecutingAssembly().Location; + key.SetValue(AppName, $"\"{exePath}\""); + Logger.Info("Auto-start enabled"); + } + else + { + key.DeleteValue(AppName, false); + Logger.Info("Auto-start disabled"); + } + } + catch (Exception ex) + { + Logger.Error($"Failed to set auto-start: {ex.Message}"); + } + } +} diff --git a/src/Moltbot.Tray.WinUI/Services/DeepLinkHandler.cs b/src/Moltbot.Tray.WinUI/Services/DeepLinkHandler.cs new file mode 100644 index 0000000..10b946f --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Services/DeepLinkHandler.cs @@ -0,0 +1,121 @@ +using Microsoft.Win32; +using System; +using System.Threading.Tasks; + +namespace MoltbotTray.Services; + +/// +/// Handles moltbot:// deep link URI scheme registration and processing. +/// +public static class DeepLinkHandler +{ + private const string UriScheme = "moltbot"; + private const string UriSchemeKey = @"SOFTWARE\Classes\moltbot"; + + public static void RegisterUriScheme() + { + try + { + var exePath = Environment.ProcessPath ?? System.Reflection.Assembly.GetExecutingAssembly().Location; + + using var key = Registry.CurrentUser.CreateSubKey(UriSchemeKey); + key?.SetValue("", "URL:Moltbot Protocol"); + key?.SetValue("URL Protocol", ""); + + using var iconKey = key?.CreateSubKey("DefaultIcon"); + iconKey?.SetValue("", $"\"{exePath}\",0"); + + using var commandKey = key?.CreateSubKey(@"shell\open\command"); + commandKey?.SetValue("", $"\"{exePath}\" \"%1\""); + + Logger.Info("URI scheme registered: moltbot://"); + } + catch (Exception ex) + { + Logger.Warn($"Failed to register URI scheme: {ex.Message}"); + } + } + + public static void Handle(string uri, DeepLinkActions actions) + { + if (!uri.StartsWith("moltbot://", StringComparison.OrdinalIgnoreCase)) + return; + + var path = uri["moltbot://".Length..].TrimEnd('/'); + var queryIndex = path.IndexOf('?'); + var query = queryIndex >= 0 ? path[(queryIndex + 1)..] : ""; + path = queryIndex >= 0 ? path[..queryIndex] : path; + + Logger.Info($"Handling deep link: {path}"); + + switch (path.ToLowerInvariant()) + { + case "settings": + actions.OpenSettings?.Invoke(); + break; + + case "chat": + actions.OpenChat?.Invoke(); + break; + + case "dashboard": + actions.OpenDashboard?.Invoke(null); + break; + + case var p when p.StartsWith("dashboard/"): + var dashboardPath = p["dashboard/".Length..]; + actions.OpenDashboard?.Invoke(dashboardPath); + break; + + case "send": + var sendMessage = GetQueryParam(query, "message"); + actions.OpenQuickSend?.Invoke(sendMessage); + break; + + case "agent": + var agentMessage = GetQueryParam(query, "message"); + if (!string.IsNullOrEmpty(agentMessage)) + { + _ = Task.Run(async () => + { + try + { + await actions.SendMessage!(agentMessage); + Logger.Info($"Sent message via deep link: {agentMessage}"); + } + catch (Exception ex) + { + Logger.Error($"Failed to send message: {ex.Message}"); + } + }); + } + break; + + default: + Logger.Warn($"Unknown deep link path: {path}"); + break; + } + } + + private static string? GetQueryParam(string query, string key) + { + foreach (var part in query.Split('&', StringSplitOptions.RemoveEmptyEntries)) + { + var kv = part.Split('=', 2); + if (kv.Length == 2 && kv[0].Equals(key, StringComparison.OrdinalIgnoreCase)) + { + return Uri.UnescapeDataString(kv[1]); + } + } + return null; + } +} + +public class DeepLinkActions +{ + public Action? OpenSettings { get; set; } + public Action? OpenChat { get; set; } + public Action? OpenDashboard { get; set; } + public Action? OpenQuickSend { get; set; } + public Func? SendMessage { get; set; } +} diff --git a/src/Moltbot.Tray.WinUI/Services/GlobalHotkeyService.cs b/src/Moltbot.Tray.WinUI/Services/GlobalHotkeyService.cs new file mode 100644 index 0000000..949f374 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Services/GlobalHotkeyService.cs @@ -0,0 +1,227 @@ +using System; +using System.Runtime.InteropServices; + +namespace MoltbotTray.Services; + +/// +/// Registers and handles global hotkeys using P/Invoke. +/// Default: Ctrl+Alt+Shift+C for Quick Send. +/// +public class GlobalHotkeyService : IDisposable +{ + private const int HOTKEY_ID = 9001; + private const uint MOD_CONTROL = 0x0002; + private const uint MOD_ALT = 0x0001; + private const uint MOD_SHIFT = 0x0004; + private const uint VK_C = 0x43; + private const int WM_HOTKEY = 0x0312; + + [DllImport("user32.dll")] + private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk); + + [DllImport("user32.dll")] + private static extern bool UnregisterHotKey(IntPtr hWnd, int id); + + [DllImport("user32.dll", SetLastError = true)] + private static extern IntPtr CreateWindowEx( + uint dwExStyle, string lpClassName, string lpWindowName, + uint dwStyle, int x, int y, int nWidth, int nHeight, + IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam); + + [DllImport("user32.dll")] + private static extern bool DestroyWindow(IntPtr hWnd); + + [DllImport("user32.dll")] + private static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll", SetLastError = true)] + private static extern ushort RegisterClass(ref WNDCLASS lpWndClass); + + [DllImport("kernel32.dll")] + private static extern IntPtr GetModuleHandle(string? lpModuleName); + + [DllImport("user32.dll")] + private static extern bool GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax); + + [DllImport("user32.dll")] + private static extern bool TranslateMessage(ref MSG lpMsg); + + [DllImport("user32.dll")] + private static extern IntPtr DispatchMessage(ref MSG lpMsg); + + [DllImport("user32.dll")] + private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); + + private const uint WM_QUIT = 0x0012; + private const uint WM_USER = 0x0400; + + private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); + + [StructLayout(LayoutKind.Sequential)] + private struct WNDCLASS + { + public uint style; + public IntPtr lpfnWndProc; + public int cbClsExtra; + public int cbWndExtra; + public IntPtr hInstance; + public IntPtr hIcon; + public IntPtr hCursor; + public IntPtr hbrBackground; + public string? lpszMenuName; + public string lpszClassName; + } + + [StructLayout(LayoutKind.Sequential)] + private struct MSG + { + public IntPtr hwnd; + public uint message; + public IntPtr wParam; + public IntPtr lParam; + public uint time; + public POINT pt; + } + + [StructLayout(LayoutKind.Sequential)] + private struct POINT + { + public int x; + public int y; + } + + private IntPtr _hwnd; + private bool _registered; + private bool _disposed; + private Thread? _messageThread; + private WndProcDelegate? _wndProcDelegate; // prevent GC collection + private volatile bool _running; + + public event EventHandler? HotkeyPressed; + + public GlobalHotkeyService() + { + } + + public bool Register() + { + if (_registered) return true; + + try + { + // Create message window on a dedicated thread with message loop + _running = true; + _messageThread = new Thread(MessageLoop) { IsBackground = true, Name = "HotkeyMessageLoop" }; + _messageThread.Start(); + + // Wait briefly for window creation + Thread.Sleep(100); + + if (_hwnd == IntPtr.Zero) + { + Logger.Warn("Failed to create hotkey message window"); + return false; + } + + _registered = RegisterHotKey(_hwnd, HOTKEY_ID, MOD_CONTROL | MOD_ALT | MOD_SHIFT, VK_C); + if (_registered) + { + Logger.Info("Global hotkey registered: Ctrl+Alt+Shift+C"); + } + else + { + Logger.Warn("Failed to register global hotkey (may be in use by another app)"); + } + return _registered; + } + catch (Exception ex) + { + Logger.Error($"Hotkey registration error: {ex.Message}"); + return false; + } + } + + private void MessageLoop() + { + try + { + // Create window class + _wndProcDelegate = WndProc; + var wndClass = new WNDCLASS + { + lpfnWndProc = Marshal.GetFunctionPointerForDelegate(_wndProcDelegate), + hInstance = GetModuleHandle(null), + lpszClassName = "MoltbotHotkeyWindow" + }; + + RegisterClass(ref wndClass); + + // Create message-only window (HWND_MESSAGE parent) + _hwnd = CreateWindowEx(0, "MoltbotHotkeyWindow", "", 0, 0, 0, 0, 0, + new IntPtr(-3), // HWND_MESSAGE + IntPtr.Zero, GetModuleHandle(null), IntPtr.Zero); + + // Message loop + while (_running && GetMessage(out MSG msg, IntPtr.Zero, 0, 0)) + { + TranslateMessage(ref msg); + DispatchMessage(ref msg); + } + } + catch (Exception ex) + { + Logger.Error($"Hotkey message loop error: {ex.Message}"); + } + } + + private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam) + { + if (msg == WM_HOTKEY && wParam.ToInt32() == HOTKEY_ID) + { + OnHotkeyPressed(); + } + return DefWindowProc(hWnd, msg, wParam, lParam); + } + + public void Unregister() + { + if (!_registered) return; + + try + { + if (_hwnd != IntPtr.Zero) + { + UnregisterHotKey(_hwnd, HOTKEY_ID); + } + _registered = false; + Logger.Info("Global hotkey unregistered"); + } + catch (Exception ex) + { + Logger.Warn($"Hotkey unregistration error: {ex.Message}"); + } + } + + internal void OnHotkeyPressed() + { + HotkeyPressed?.Invoke(this, EventArgs.Empty); + } + + public void Dispose() + { + if (_disposed) return; + _disposed = true; + + Unregister(); + + _running = false; + if (_hwnd != IntPtr.Zero) + { + PostMessage(_hwnd, WM_QUIT, IntPtr.Zero, IntPtr.Zero); + DestroyWindow(_hwnd); + _hwnd = IntPtr.Zero; + } + + _messageThread?.Join(1000); + } +} diff --git a/src/Moltbot.Tray.WinUI/Services/Logger.cs b/src/Moltbot.Tray.WinUI/Services/Logger.cs new file mode 100644 index 0000000..6adda66 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Services/Logger.cs @@ -0,0 +1,63 @@ +using System; +using System.IO; + +namespace MoltbotTray.Services; + +/// +/// Simple file logger for the tray application. +/// +public static class Logger +{ + private static readonly object _lock = new(); + private static readonly string _logDirectory; + private static readonly string _logFilePath; + + static Logger() + { + _logDirectory = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "MoltbotTray"); + + Directory.CreateDirectory(_logDirectory); + _logFilePath = Path.Combine(_logDirectory, "moltbot-tray.log"); + + // Rotate log if too large (> 5MB) + try + { + var fileInfo = new FileInfo(_logFilePath); + if (fileInfo.Exists && fileInfo.Length > 5 * 1024 * 1024) + { + var backupPath = Path.Combine(_logDirectory, "moltbot-tray.log.old"); + if (File.Exists(backupPath)) File.Delete(backupPath); + File.Move(_logFilePath, backupPath); + } + } + catch { } + } + + public static string LogFilePath => _logFilePath; + + public static void Info(string message) => Log("INFO", message); + public static void Warn(string message) => Log("WARN", message); + public static void Error(string message) => Log("ERROR", message); + public static void Debug(string message) => Log("DEBUG", message); + + private static void Log(string level, string message) + { + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + var line = $"[{timestamp}] [{level}] {message}"; + + lock (_lock) + { + try + { + File.AppendAllText(_logFilePath, line + Environment.NewLine); + } + catch { } + } + +#if DEBUG + System.Diagnostics.Debug.WriteLine(line); +#endif + } +} diff --git a/src/Moltbot.Tray.WinUI/Services/NotificationHistoryService.cs b/src/Moltbot.Tray.WinUI/Services/NotificationHistoryService.cs new file mode 100644 index 0000000..f9f9cb5 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Services/NotificationHistoryService.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MoltbotTray.Services; + +/// +/// Stores notification history in memory with a configurable limit. +/// +public static class NotificationHistoryService +{ + private static readonly List _history = new(); + private static readonly object _lock = new(); + private const int MaxHistory = 100; + + public static void AddNotification(GatewayNotification notification) + { + lock (_lock) + { + _history.Insert(0, new NotificationHistoryItem + { + Timestamp = DateTime.Now, + Title = notification.Title ?? "Moltbot", + Message = notification.Message ?? "", + Category = notification.Category, + ActionUrl = notification.ActionUrl + }); + + // Trim to max + while (_history.Count > MaxHistory) + { + _history.RemoveAt(_history.Count - 1); + } + } + } + + public static IReadOnlyList GetHistory() + { + lock (_lock) + { + return _history.ToList(); + } + } + + public static void Clear() + { + lock (_lock) + { + _history.Clear(); + } + } +} + +public class NotificationHistoryItem +{ + public DateTime Timestamp { get; set; } + public string Title { get; set; } = ""; + public string Message { get; set; } = ""; + public string? Category { get; set; } + public string? ActionUrl { get; set; } +} + +// Local notification model +public class GatewayNotification +{ + public string? Title { get; set; } + public string? Message { get; set; } + public string? Category { get; set; } + public string? ActionUrl { get; set; } +} diff --git a/src/Moltbot.Tray.WinUI/Services/SettingsManager.cs b/src/Moltbot.Tray.WinUI/Services/SettingsManager.cs new file mode 100644 index 0000000..fc8a1f2 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Services/SettingsManager.cs @@ -0,0 +1,131 @@ +using System; +using System.IO; +using System.Text.Json; + +namespace MoltbotTray.Services; + +/// +/// Manages application settings with JSON persistence. +/// +public class SettingsManager +{ + private static readonly string SettingsDirectory = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + "MoltbotTray"); + + private static readonly string SettingsFilePath = Path.Combine(SettingsDirectory, "settings.json"); + + // Connection + public string GatewayUrl { get; set; } = "ws://localhost:18789"; + public string Token { get; set; } = ""; + + // Startup + public bool AutoStart { get; set; } = false; + public bool GlobalHotkeyEnabled { get; set; } = true; + + // Notifications + public bool ShowNotifications { get; set; } = true; + public string NotificationSound { get; set; } = "Default"; + + // Notification filters + public bool NotifyHealth { get; set; } = true; + public bool NotifyUrgent { get; set; } = true; + public bool NotifyReminder { get; set; } = true; + public bool NotifyEmail { get; set; } = true; + public bool NotifyCalendar { get; set; } = true; + public bool NotifyBuild { get; set; } = true; + public bool NotifyStock { get; set; } = true; + public bool NotifyInfo { get; set; } = true; + + public SettingsManager() + { + Load(); + } + + public void Load() + { + try + { + if (File.Exists(SettingsFilePath)) + { + var json = File.ReadAllText(SettingsFilePath); + var loaded = JsonSerializer.Deserialize(json); + if (loaded != null) + { + GatewayUrl = loaded.GatewayUrl ?? GatewayUrl; + Token = loaded.Token ?? Token; + AutoStart = loaded.AutoStart; + GlobalHotkeyEnabled = loaded.GlobalHotkeyEnabled; + ShowNotifications = loaded.ShowNotifications; + NotificationSound = loaded.NotificationSound ?? NotificationSound; + NotifyHealth = loaded.NotifyHealth; + NotifyUrgent = loaded.NotifyUrgent; + NotifyReminder = loaded.NotifyReminder; + NotifyEmail = loaded.NotifyEmail; + NotifyCalendar = loaded.NotifyCalendar; + NotifyBuild = loaded.NotifyBuild; + NotifyStock = loaded.NotifyStock; + NotifyInfo = loaded.NotifyInfo; + } + } + } + catch (Exception ex) + { + Logger.Warn($"Failed to load settings: {ex.Message}"); + } + } + + public void Save() + { + try + { + Directory.CreateDirectory(SettingsDirectory); + + var data = new SettingsData + { + GatewayUrl = GatewayUrl, + Token = Token, + AutoStart = AutoStart, + GlobalHotkeyEnabled = GlobalHotkeyEnabled, + ShowNotifications = ShowNotifications, + NotificationSound = NotificationSound, + NotifyHealth = NotifyHealth, + NotifyUrgent = NotifyUrgent, + NotifyReminder = NotifyReminder, + NotifyEmail = NotifyEmail, + NotifyCalendar = NotifyCalendar, + NotifyBuild = NotifyBuild, + NotifyStock = NotifyStock, + NotifyInfo = NotifyInfo + }; + + var options = new JsonSerializerOptions { WriteIndented = true }; + var json = JsonSerializer.Serialize(data, options); + File.WriteAllText(SettingsFilePath, json); + + Logger.Info("Settings saved"); + } + catch (Exception ex) + { + Logger.Error($"Failed to save settings: {ex.Message}"); + } + } + + private class SettingsData + { + public string? GatewayUrl { get; set; } + public string? Token { get; set; } + public bool AutoStart { get; set; } + public bool GlobalHotkeyEnabled { get; set; } = true; + public bool ShowNotifications { get; set; } = true; + public string? NotificationSound { get; set; } + public bool NotifyHealth { get; set; } = true; + public bool NotifyUrgent { get; set; } = true; + public bool NotifyReminder { get; set; } = true; + public bool NotifyEmail { get; set; } = true; + public bool NotifyCalendar { get; set; } = true; + public bool NotifyBuild { get; set; } = true; + public bool NotifyStock { get; set; } = true; + public bool NotifyInfo { get; set; } = true; + } +} diff --git a/src/Moltbot.Tray.WinUI/Windows/NotificationHistoryWindow.xaml b/src/Moltbot.Tray.WinUI/Windows/NotificationHistoryWindow.xaml new file mode 100644 index 0000000..69799a3 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Windows/NotificationHistoryWindow.xaml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Moltbot.Tray.WinUI/Windows/WebChatWindow.xaml.cs b/src/Moltbot.Tray.WinUI/Windows/WebChatWindow.xaml.cs new file mode 100644 index 0000000..1112ce9 --- /dev/null +++ b/src/Moltbot.Tray.WinUI/Windows/WebChatWindow.xaml.cs @@ -0,0 +1,148 @@ +using Microsoft.UI.Xaml; +using Microsoft.Web.WebView2.Core; +using Moltbot.Shared; +using MoltbotTray.Helpers; +using MoltbotTray.Services; +using System; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using WinUIEx; +using Windows.Foundation; + +namespace MoltbotTray.Windows; + +public sealed partial class WebChatWindow : WindowEx +{ + private readonly string _gatewayUrl; + private readonly string _token; + private bool _initialized; + + // Store event handlers for cleanup + private TypedEventHandler? _navigationCompletedHandler; + private TypedEventHandler? _navigationStartingHandler; + + public bool IsClosed { get; private set; } + + public WebChatWindow(string gatewayUrl, string token) + { + _gatewayUrl = gatewayUrl; + _token = token; + + InitializeComponent(); + + // Window configuration + this.SetWindowSize(520, 750); + this.MinWidth = 380; + this.MinHeight = 450; + this.CenterOnScreen(); + this.SetIcon(IconHelper.GetStatusIconPath(ConnectionStatus.Connected)); + + Closed += OnWindowClosed; + + _ = InitializeWebViewAsync(); + } + + private void OnWindowClosed(object sender, WindowEventArgs e) + { + IsClosed = true; + + // Cleanup WebView2 event handlers + if (WebView.CoreWebView2 != null) + { + if (_navigationCompletedHandler != null) + WebView.CoreWebView2.NavigationCompleted -= _navigationCompletedHandler; + if (_navigationStartingHandler != null) + WebView.CoreWebView2.NavigationStarting -= _navigationStartingHandler; + } + } + + private async Task InitializeWebViewAsync() + { + try + { + // Set up user data folder via environment variable (WinUI 3 workaround) + var userDataFolder = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "MoltbotTray", "WebView2"); + + Directory.CreateDirectory(userDataFolder); + Environment.SetEnvironmentVariable("WEBVIEW2_USER_DATA_FOLDER", userDataFolder); + + await WebView.EnsureCoreWebView2Async(); + + // Configure WebView2 + WebView.CoreWebView2.Settings.IsStatusBarEnabled = false; + WebView.CoreWebView2.Settings.AreDefaultContextMenusEnabled = true; + WebView.CoreWebView2.Settings.IsZoomControlEnabled = true; + + // Handle navigation events (store for cleanup) + _navigationCompletedHandler = (s, e) => + { + LoadingRing.IsActive = false; + LoadingRing.Visibility = Visibility.Collapsed; + }; + WebView.CoreWebView2.NavigationCompleted += _navigationCompletedHandler; + + _navigationStartingHandler = (s, e) => + { + LoadingRing.IsActive = true; + LoadingRing.Visibility = Visibility.Visible; + }; + WebView.CoreWebView2.NavigationStarting += _navigationStartingHandler; + + // Navigate to chat + NavigateToChat(); + _initialized = true; + } + catch (Exception ex) + { + Logger.Error($"WebView2 initialization failed: {ex.Message}"); + LoadingRing.IsActive = false; + } + } + + private void NavigateToChat() + { + if (WebView.CoreWebView2 == null) return; + + var baseUrl = _gatewayUrl + .Replace("ws://", "http://") + .Replace("wss://", "https://"); + + var url = $"{baseUrl}?token={Uri.EscapeDataString(_token)}"; + WebView.CoreWebView2.Navigate(url); + } + + private void OnHome(object sender, RoutedEventArgs e) + { + NavigateToChat(); + } + + private void OnRefresh(object sender, RoutedEventArgs e) + { + WebView.CoreWebView2?.Reload(); + } + + private void OnPopout(object sender, RoutedEventArgs e) + { + var baseUrl = _gatewayUrl + .Replace("ws://", "http://") + .Replace("wss://", "https://"); + var url = $"{baseUrl}?token={Uri.EscapeDataString(_token)}"; + + try + { + Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); + } + catch (Exception ex) + { + Logger.Error($"Failed to open in browser: {ex.Message}"); + } + } + + private void OnDevTools(object sender, RoutedEventArgs e) + { + WebView.CoreWebView2?.OpenDevToolsWindow(); + } +} diff --git a/src/Moltbot.Tray.WinUI/app.manifest b/src/Moltbot.Tray.WinUI/app.manifest new file mode 100644 index 0000000..917a80a --- /dev/null +++ b/src/Moltbot.Tray.WinUI/app.manifest @@ -0,0 +1,19 @@ + + + + + + + + true/pm + PerMonitorV2 + + + + + + + + + +