From 554f972bd1e44f4d0559ea05e37302fe7dd5ad7d Mon Sep 17 00:00:00 2001
From: Kristen Schau <47155823+krschau@users.noreply.github.com>
Date: Thu, 14 Mar 2024 11:21:14 -0400
Subject: [PATCH 001/121] Have IThemeSelectorService notify for
ActualThemeChanged (#2395)
---
common/Services/IThemeSelectorService.cs | 3 +++
src/ViewModels/ShellViewModel.cs | 20 ++++++++++---------
src/Views/ShellPage.xaml.cs | 7 +++----
.../Services/AdaptiveCardRenderingService.cs | 6 +++++-
.../Services/IAdaptiveCardRenderingService.cs | 3 ++-
.../Views/DashboardView.xaml | 11 ++++++++++
.../Views/DashboardView.xaml.cs | 19 +++++++++---------
.../ViewModels/RepoConfigViewModel.cs | 11 ++--------
.../Views/RepoConfigView.xaml.cs | 9 ---------
9 files changed, 47 insertions(+), 42 deletions(-)
diff --git a/common/Services/IThemeSelectorService.cs b/common/Services/IThemeSelectorService.cs
index b55fcb2fa2..8d02e5e1b0 100644
--- a/common/Services/IThemeSelectorService.cs
+++ b/common/Services/IThemeSelectorService.cs
@@ -9,6 +9,9 @@ namespace DevHome.Contracts.Services;
public interface IThemeSelectorService
{
+ ///
+ /// Occurs when the theme has changed, either due to user selection or the system theme changing.
+ ///
public event EventHandler ThemeChanged;
ElementTheme Theme { get; }
diff --git a/src/ViewModels/ShellViewModel.cs b/src/ViewModels/ShellViewModel.cs
index 96fcdd95f3..1680ee4fd6 100644
--- a/src/ViewModels/ShellViewModel.cs
+++ b/src/ViewModels/ShellViewModel.cs
@@ -14,21 +14,16 @@ public partial class ShellViewModel : ObservableObject
{
private readonly ILocalSettingsService _localSettingsService;
private readonly IAppInfoService _appInfoService;
+ private readonly IThemeSelectorService _themeSelectorService;
[ObservableProperty]
private string? _announcementText;
public string Title => _appInfoService.GetAppNameLocalized();
- public INavigationService NavigationService
- {
- get;
- }
+ public INavigationService NavigationService { get; }
- public INavigationViewService NavigationViewService
- {
- get;
- }
+ public INavigationViewService NavigationViewService { get; }
[ObservableProperty]
private object? _selected;
@@ -41,13 +36,15 @@ public ShellViewModel(
INavigationViewService navigationViewService,
ILocalSettingsService localSettingsService,
IScreenReaderService screenReaderService,
- IAppInfoService appInfoService)
+ IAppInfoService appInfoService,
+ IThemeSelectorService themeSelectorService)
{
NavigationService = navigationService;
NavigationService.Navigated += OnNavigated;
NavigationViewService = navigationViewService;
_localSettingsService = localSettingsService;
_appInfoService = appInfoService;
+ _themeSelectorService = themeSelectorService;
screenReaderService.AnnouncementTextChanged += OnAnnouncementTextChanged;
}
@@ -98,4 +95,9 @@ private void OnAnnouncementTextChanged(object? sender, string text)
// Set new announcement title
AnnouncementText = text;
}
+
+ internal void NotifyActualThemeChanged()
+ {
+ _themeSelectorService.SetRequestedTheme();
+ }
}
diff --git a/src/Views/ShellPage.xaml.cs b/src/Views/ShellPage.xaml.cs
index a51b0d3e17..e8d7e875fe 100644
--- a/src/Views/ShellPage.xaml.cs
+++ b/src/Views/ShellPage.xaml.cs
@@ -17,10 +17,7 @@ namespace DevHome.Views;
public sealed partial class ShellPage : Page
{
- public ShellViewModel ViewModel
- {
- get;
- }
+ public ShellViewModel ViewModel { get; }
public ShellPage(ShellViewModel viewModel)
{
@@ -59,6 +56,8 @@ private void OnActualThemeChanged(FrameworkElement sender, object args)
// Update the title bar if the system theme changes.
TitleBarHelper.UpdateTitleBar(App.MainWindow, ActualTheme);
AppTitleBar.Repaint();
+
+ ViewModel.NotifyActualThemeChanged();
}
private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
diff --git a/tools/Dashboard/DevHome.Dashboard/Services/AdaptiveCardRenderingService.cs b/tools/Dashboard/DevHome.Dashboard/Services/AdaptiveCardRenderingService.cs
index 3a68c1b8a9..6535f7356c 100644
--- a/tools/Dashboard/DevHome.Dashboard/Services/AdaptiveCardRenderingService.cs
+++ b/tools/Dashboard/DevHome.Dashboard/Services/AdaptiveCardRenderingService.cs
@@ -16,6 +16,8 @@ namespace DevHome.Dashboard.Services;
public class AdaptiveCardRenderingService : IAdaptiveCardRenderingService, IDisposable
{
+ public event EventHandler RendererUpdated = (_, _) => { };
+
private readonly WindowEx _windowEx;
private readonly IThemeSelectorService _themeSelectorService;
@@ -94,7 +96,7 @@ private async Task ConfigureWidgetRenderer()
};
}
- public async Task UpdateHostConfig()
+ private async Task UpdateHostConfig()
{
if (_renderer != null)
{
@@ -127,6 +129,8 @@ public async Task UpdateHostConfig()
Log.Logger()?.ReportError("DashboardView", $"HostConfig contents are {hostConfigContents}");
}
});
+
+ RendererUpdated(this, null);
}
}
diff --git a/tools/Dashboard/DevHome.Dashboard/Services/IAdaptiveCardRenderingService.cs b/tools/Dashboard/DevHome.Dashboard/Services/IAdaptiveCardRenderingService.cs
index 07603bd2ea..97e244e446 100644
--- a/tools/Dashboard/DevHome.Dashboard/Services/IAdaptiveCardRenderingService.cs
+++ b/tools/Dashboard/DevHome.Dashboard/Services/IAdaptiveCardRenderingService.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+using System;
using System.Threading.Tasks;
using AdaptiveCards.Rendering.WinUI3;
@@ -10,5 +11,5 @@ public interface IAdaptiveCardRenderingService
{
public Task GetRenderer();
- public Task UpdateHostConfig();
+ public event EventHandler RendererUpdated;
}
diff --git a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml
index 3b3bd3d829..0c02bf3f56 100644
--- a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml
+++ b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml
@@ -14,6 +14,8 @@
xmlns:controls="using:DevHome.Dashboard.Controls"
xmlns:behaviors="using:DevHome.Common.Behaviors"
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
+ xmlns:i="using:Microsoft.Xaml.Interactivity"
+ xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
behaviors:NavigationViewHeaderBehavior.HeaderMode="Never"
mc:Ignorable="d">
@@ -33,6 +35,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs
index f987179c8c..1317cb488b 100644
--- a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs
+++ b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs
@@ -66,10 +66,6 @@ public DashboardView()
_dispatcher = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
_localSettingsService = Application.Current.GetService();
- ActualThemeChanged += OnActualThemeChanged;
-
- Loaded += OnLoaded;
-
#if DEBUG
Loaded += AddResetButton;
#endif
@@ -102,11 +98,8 @@ private async Task SubscribeToWidgetCatalogEventsAsync()
return true;
}
- private async void OnActualThemeChanged(FrameworkElement sender, object args)
+ private async void HandleRendererUpdated(object sender, object args)
{
- // A different host config is used to render widgets (adaptive cards) in light and dark themes.
- await Application.Current.GetService().UpdateHostConfig();
-
// Re-render the widgets with the new theme and renderer.
foreach (var widget in PinnedWidgets)
{
@@ -114,11 +107,19 @@ private async void OnActualThemeChanged(FrameworkElement sender, object args)
}
}
- private async void OnLoaded(object sender, RoutedEventArgs e)
+ [RelayCommand]
+ private async Task OnLoadedAsync()
{
+ Application.Current.GetService().RendererUpdated += HandleRendererUpdated;
await InitializeDashboard();
}
+ [RelayCommand]
+ private void OnUnloaded()
+ {
+ Application.Current.GetService().RendererUpdated -= HandleRendererUpdated;
+ }
+
private async Task InitializeDashboard()
{
LoadingWidgetsProgressRing.Visibility = Visibility.Visible;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs
index 7567ba375d..e0b9189210 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/RepoConfigViewModel.cs
@@ -118,19 +118,12 @@ public RepoConfigViewModel(
: stringResource.GetLocalized(StringResourceKey.SetupShellRepoConfigTargetMachine);
}
- private void OnThemeChanged(object sender, ElementTheme e)
+ private void OnThemeChanged(object sender, ElementTheme newRequestedTheme)
{
- var themeToSwitchTo = e;
-
- if (themeToSwitchTo == ElementTheme.Default)
- {
- themeToSwitchTo = _themeSelectorService.GetActualTheme();
- }
-
// Because the logos aren't glyphs DevHome has to change the logos manually to match the theme.
foreach (var cloneInformation in RepoReviewItems)
{
- cloneInformation.SetIcon(themeToSwitchTo);
+ cloneInformation.SetIcon(_themeSelectorService.GetActualTheme());
}
}
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/RepoConfigView.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/RepoConfigView.xaml.cs
index bbcce1ce31..c0a90a74a3 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/RepoConfigView.xaml.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/RepoConfigView.xaml.cs
@@ -39,15 +39,6 @@ public RepoConfigView()
public void OnActualThemeChanged(FrameworkElement sender, object args)
{
- if (ViewModel != null)
- {
- // Because the logos aren't glyphs DevHome has to change the logos manually to match the theme.
- foreach (var cloneInformation in ViewModel.RepoReviewItems)
- {
- cloneInformation.SetIcon(sender.ActualTheme);
- }
- }
-
if (_addRepoDialog != null)
{
_addRepoDialog.RequestedTheme = sender.ActualTheme;
From 4135b62b4f1151657847bb074d421ac66ab7d7d5 Mon Sep 17 00:00:00 2001
From: Jeff Whiteside
Date: Thu, 14 Mar 2024 09:16:08 -0700
Subject: [PATCH 002/121] =?UTF-8?q?Experimental=20Feature:=20Quiet=20Backg?=
=?UTF-8?q?round=20Processes=20UI=20and=20WinRT=20server=20=E2=80=A6=20(#2?=
=?UTF-8?q?322)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Experimental Feature: Quiet Background Processes UI and WinRT server (/w Self-Elevation)
Adding the "Enable 'Quiet Background Processes'" experimental feature to Dev Home.
It's a toggle that is enabled similarly to Focus Assist mode, that expires after a period of time.
When you enable it/toggle it on via the UI, Dev Home will call into the OS to enable quieting down background services (e.g. Search Indexer).
* Works on supported OSes
* Requires a split-token user (for UAC prompt) or Over-The-Shoulder credentials to consume the feature
---
.github/workflows/DevHome-CI.yml | 1 +
DevHome.sln | 97 +++++++++
Directory.CppBuild.props | 8 +
common/DevHome.Common.csproj | 2 +-
.../Strings/en-us/Resources.resw | 8 +
src/DevHome.csproj | 28 +++
src/NavConfig.jsonc | 29 +++
src/Package.appxmanifest | 18 +-
test/DevHome.Test.csproj | 2 +-
.../DevHome.Dashboard.UnitTest.csproj | 2 +-
.../src/DevHome.Experiments.csproj | 3 +-
.../src/Strings/en-us/Resources.resw | 136 ++++++------
tools/QuietBackgroundProcesses/.gitattributes | 3 +
...me.QuietBackgroundProcesses.Common.vcxproj | 195 +++++++++++++++++
.../DevHome.QuietBackgroundProcesses.idl | 25 +++
.../PropertySheet.props | 16 ++
.../Utility.h | 140 ++++++++++++
.../empty.cpp | 5 +
...Processes.ElevatedServer.Projection.csproj | 36 ++++
...BackgroundProcesses.ElevatedServer.vcxproj | 173 +++++++++++++++
.../PropertySheet.props | 16 ++
.../QuietBackgroundProcessesSession.cpp | 136 ++++++++++++
.../QuietState.cpp | 27 +++
.../QuietState.h | 16 ++
.../TimedQuietSession.h | 143 +++++++++++++
.../Timer.h | 114 ++++++++++
.../main.cpp | 109 ++++++++++
.../packages.config | 5 +
.../pch.cpp | 4 +
.../pch.h | 10 +
...me.QuietBackgroundProcesses.Server.vcxproj | 175 +++++++++++++++
.../PropertySheet.props | 16 ++
...QuietBackgroundProcessesSessionManager.cpp | 89 ++++++++
.../main.cpp | 80 +++++++
.../packages.config | 5 +
.../pch.cpp | 4 +
.../pch.h | 10 +
...DevHome.QuietBackgroundProcesses.UI.csproj | 22 ++
.../Strings/en-us/Resources.resw | 111 ++++++++++
.../QuietBackgroundProcessesViewModel.cs | 200 ++++++++++++++++++
.../Views/QuietBackgroundProcessesPage.xaml | 44 ++++
.../QuietBackgroundProcessesPage.xaml.cs | 26 +++
42 files changed, 2216 insertions(+), 73 deletions(-)
create mode 100644 Directory.CppBuild.props
create mode 100644 tools/QuietBackgroundProcesses/.gitattributes
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/empty.cpp
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml
create mode 100644 tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml.cs
diff --git a/.github/workflows/DevHome-CI.yml b/.github/workflows/DevHome-CI.yml
index 8c6df009b4..e808d2a70d 100644
--- a/.github/workflows/DevHome-CI.yml
+++ b/.github/workflows/DevHome-CI.yml
@@ -60,6 +60,7 @@ jobs:
run: |
cmd /c "$env:VSDevCmd" "&" msbuild -t:restore /m /p:Configuration=Release,Platform=${{ matrix.platform }},RestorePackagesConfig=true extensionsdk\\DevHomeSDK.sln
cmd /c "$env:VSDevCmd" "&" msbuild -t:restore /m /p:Configuration=Release,Platform=${{ matrix.platform }} DevHome.sln
+ cmd /c ".\.nuget\nuget.exe restore"
- name: Build_SDK
run: cmd /c "$env:VSDevCmd" "&" msbuild /p:Configuration=Release,Platform=${{ matrix.platform }} extensionsdk\\DevHomeSDK.sln
diff --git a/DevHome.sln b/DevHome.sln
index 068148209b..87ee93969b 100644
--- a/DevHome.sln
+++ b/DevHome.sln
@@ -72,6 +72,17 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExtensionLibrary", "Extensi
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.Experiments", "tools\Experiments\src\DevHome.Experiments.csproj", "{2F9AD5AF-EF3B-496A-8566-9E9539E3DF43}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "QuietBackgroundProcesses", "QuietBackgroundProcesses", "{D04CD3A1-0B45-4CB3-925F-204F5F6AE2D8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DevHome.QuietBackgroundProcesses.ElevatedServer", "tools\QuietBackgroundProcesses\DevHome.QuietBackgroundProcesses.ElevatedServer\DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj", "{75945141-03AC-4C40-A586-16D463A0AC1B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.QuietBackgroundProcesses.ElevatedServer.Projection", "tools\QuietBackgroundProcesses\DevHome.QuietBackgroundProcesses.ElevatedServer.Projection\DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj", "{092AC740-DA01-4872-8E93-B9557DAD6BE5}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DevHome.QuietBackgroundProcesses.Server", "tools\QuietBackgroundProcesses\DevHome.QuietBackgroundProcesses.Server\DevHome.QuietBackgroundProcesses.Server.vcxproj", "{80805B43-CE75-4C6E-92F8-F385C1039E53}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DevHome.QuietBackgroundProcesses.Common", "tools\QuietBackgroundProcesses\DevHome.QuietBackgroundProcesses.Common\DevHome.QuietBackgroundProcesses.Common.vcxproj", "{4B370E2F-FB1D-4887-90BF-3B72517485CE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.QuietBackgroundProcesses.UI", "tools\QuietBackgroundProcesses\DevHome.QuietBackgroundProcesses.UI\DevHome.QuietBackgroundProcesses.UI.csproj", "{1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{DCAF188B-60C3-4EDB-8049-BAA927FBCD7D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleTool", "SampleTool", "{E7C94F61-D6CF-464D-8D50-210488AF7A50}"
@@ -454,6 +465,86 @@ Global
{2F9AD5AF-EF3B-496A-8566-9E9539E3DF43}.Release|x64.Build.0 = Release|x64
{2F9AD5AF-EF3B-496A-8566-9E9539E3DF43}.Release|x86.ActiveCfg = Release|x86
{2F9AD5AF-EF3B-496A-8566-9E9539E3DF43}.Release|x86.Build.0 = Release|x86
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Debug|Any CPU.Build.0 = Debug|x64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Debug|arm64.ActiveCfg = Debug|ARM64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Debug|arm64.Build.0 = Debug|ARM64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Debug|x64.ActiveCfg = Debug|x64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Debug|x64.Build.0 = Debug|x64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Debug|x86.ActiveCfg = Debug|Win32
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Debug|x86.Build.0 = Debug|Win32
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Release|Any CPU.ActiveCfg = Release|x64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Release|Any CPU.Build.0 = Release|x64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Release|arm64.ActiveCfg = Release|ARM64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Release|arm64.Build.0 = Release|ARM64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Release|x64.ActiveCfg = Release|x64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Release|x64.Build.0 = Release|x64
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Release|x86.ActiveCfg = Release|Win32
+ {75945141-03AC-4C40-A586-16D463A0AC1B}.Release|x86.Build.0 = Release|Win32
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Debug|Any CPU.Build.0 = Debug|x64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Debug|arm64.ActiveCfg = Debug|ARM64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Debug|arm64.Build.0 = Debug|ARM64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Debug|x64.ActiveCfg = Debug|x64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Debug|x64.Build.0 = Debug|x64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Debug|x86.ActiveCfg = Debug|x86
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Debug|x86.Build.0 = Debug|x86
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Release|Any CPU.ActiveCfg = Release|x64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Release|Any CPU.Build.0 = Release|x64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Release|arm64.ActiveCfg = Release|ARM64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Release|arm64.Build.0 = Release|ARM64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Release|x64.ActiveCfg = Release|x64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Release|x64.Build.0 = Release|x64
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Release|x86.ActiveCfg = Release|x86
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5}.Release|x86.Build.0 = Release|x86
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Debug|Any CPU.Build.0 = Debug|x64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Debug|arm64.ActiveCfg = Debug|ARM64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Debug|arm64.Build.0 = Debug|ARM64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Debug|x64.ActiveCfg = Debug|x64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Debug|x64.Build.0 = Debug|x64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Debug|x86.ActiveCfg = Debug|Win32
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Debug|x86.Build.0 = Debug|Win32
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Release|Any CPU.ActiveCfg = Release|x64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Release|Any CPU.Build.0 = Release|x64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Release|arm64.ActiveCfg = Release|ARM64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Release|arm64.Build.0 = Release|ARM64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Release|x64.ActiveCfg = Release|x64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Release|x64.Build.0 = Release|x64
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Release|x86.ActiveCfg = Release|Win32
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}.Release|x86.Build.0 = Release|Win32
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Debug|Any CPU.Build.0 = Debug|x64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Debug|arm64.ActiveCfg = Debug|ARM64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Debug|arm64.Build.0 = Debug|ARM64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Debug|x64.ActiveCfg = Debug|x64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Debug|x64.Build.0 = Debug|x64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Debug|x86.ActiveCfg = Debug|Win32
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Debug|x86.Build.0 = Debug|Win32
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Release|Any CPU.ActiveCfg = Release|x64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Release|Any CPU.Build.0 = Release|x64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Release|arm64.ActiveCfg = Release|ARM64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Release|arm64.Build.0 = Release|ARM64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Release|x64.ActiveCfg = Release|x64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Release|x64.Build.0 = Release|x64
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Release|x86.ActiveCfg = Release|Win32
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}.Release|x86.Build.0 = Release|Win32
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Debug|Any CPU.Build.0 = Debug|x64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Debug|arm64.ActiveCfg = Debug|arm64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Debug|arm64.Build.0 = Debug|arm64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Debug|x64.ActiveCfg = Debug|x64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Debug|x64.Build.0 = Debug|x64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Debug|x86.ActiveCfg = Debug|x86
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Debug|x86.Build.0 = Debug|x86
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Release|Any CPU.ActiveCfg = Release|x64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Release|Any CPU.Build.0 = Release|x64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Release|arm64.ActiveCfg = Release|arm64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Release|arm64.Build.0 = Release|arm64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Release|x64.ActiveCfg = Release|x64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Release|x64.Build.0 = Release|x64
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Release|x86.ActiveCfg = Release|x86
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE}.Release|x86.Build.0 = Release|x86
{CFD8A90D-8B6D-4ED6-BA35-FF894BEB46C0}.Debug|Any CPU.ActiveCfg = Debug|x64
{CFD8A90D-8B6D-4ED6-BA35-FF894BEB46C0}.Debug|Any CPU.Build.0 = Debug|x64
{CFD8A90D-8B6D-4ED6-BA35-FF894BEB46C0}.Debug|arm64.ActiveCfg = Debug|ARM64
@@ -700,6 +791,12 @@ Global
{69F8B7DF-F52B-4B74-9A16-AB3241BB8912} = {F6EAB7D3-8F0A-4455-8969-2EF4A67314A0}
{F6EAB7D3-8F0A-4455-8969-2EF4A67314A0} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD}
{2F9AD5AF-EF3B-496A-8566-9E9539E3DF43} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD}
+ {D04CD3A1-0B45-4CB3-925F-204F5F6AE2D8} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD}
+ {75945141-03AC-4C40-A586-16D463A0AC1B} = {D04CD3A1-0B45-4CB3-925F-204F5F6AE2D8}
+ {092AC740-DA01-4872-8E93-B9557DAD6BE5} = {D04CD3A1-0B45-4CB3-925F-204F5F6AE2D8}
+ {80805B43-CE75-4C6E-92F8-F385C1039E53} = {D04CD3A1-0B45-4CB3-925F-204F5F6AE2D8}
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE} = {D04CD3A1-0B45-4CB3-925F-204F5F6AE2D8}
+ {1477F3EA-A9F6-4B4F-82F4-C2427F57EBEE} = {D04CD3A1-0B45-4CB3-925F-204F5F6AE2D8}
{E7C94F61-D6CF-464D-8D50-210488AF7A50} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD}
{8FC9A04E-1FFD-42BA-B304-D1FA964D99CE} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD}
{CFD8A90D-8B6D-4ED6-BA35-FF894BEB46C0} = {8FC9A04E-1FFD-42BA-B304-D1FA964D99CE}
diff --git a/Directory.CppBuild.props b/Directory.CppBuild.props
new file mode 100644
index 0000000000..280febbe6d
--- /dev/null
+++ b/Directory.CppBuild.props
@@ -0,0 +1,8 @@
+
+
+ $(Platform)
+ x86
+ $(SolutionDir)tools\bin\$(CppPlatformTarget)\$(Configuration)\
+ $(CppBaseOutDir)$(MSBuildProjectName)\
+
+
\ No newline at end of file
diff --git a/common/DevHome.Common.csproj b/common/DevHome.Common.csproj
index f2c411809a..3cf6850d84 100644
--- a/common/DevHome.Common.csproj
+++ b/common/DevHome.Common.csproj
@@ -34,7 +34,7 @@
-
+
diff --git a/settings/DevHome.Settings/Strings/en-us/Resources.resw b/settings/DevHome.Settings/Strings/en-us/Resources.resw
index b1dc31a39e..c1dcbd8a1b 100644
--- a/settings/DevHome.Settings/Strings/en-us/Resources.resw
+++ b/settings/DevHome.Settings/Strings/en-us/Resources.resw
@@ -558,4 +558,12 @@
Environments Configuration
Title text for the Environments configuration feature.
+
+ Quiet background processes experiment
+ Name of experimental feature ()'Quiet Background Processes') on the 'Settings -> Experiments' page where you enable it.
+
+
+ Silence and track background processes that may hinder device performance
+ Inline description of the Quiet Background Processes experimental feature on the 'Settings -> Experiments' page where you enable it.
+
\ No newline at end of file
diff --git a/src/DevHome.csproj b/src/DevHome.csproj
index 0d127cc0df..77c167e1f9 100644
--- a/src/DevHome.csproj
+++ b/src/DevHome.csproj
@@ -3,6 +3,7 @@
+
WinExe
@@ -60,6 +61,7 @@
+
all
@@ -75,6 +77,10 @@
+
+
+
+
@@ -103,9 +109,31 @@
true
+
+
+
+ <_DevHomeInternal_CppPlatform>$(Platform)
+ <_DevHomeInternal_CppPlatform Condition="'$(Platform)' == 'x86'">Win32
+ $(DevHomeInternal_Win32RuntimePath)$(_DevHomeInternal_CppPlatform)\
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
$(DefineConstants);CANARY_BUILD
$(DefineConstants);STABLE_BUILD
+
diff --git a/src/NavConfig.jsonc b/src/NavConfig.jsonc
index 867f9da0d2..4d570e97dc 100644
--- a/src/NavConfig.jsonc
+++ b/src/NavConfig.jsonc
@@ -32,6 +32,14 @@
"viewFullName": "DevHome.Environments.Views.LandingPage",
"viewModelFullName": "DevHome.Environments.ViewModels.LandingPageViewModel",
"icon": "E83B"
+ },
+ {
+ "identity": "DevHome.QuietBackgroundProcesses.UI",
+ "assembly": "DevHome.QuietBackgroundProcesses.UI",
+ "viewFullName": "DevHome.QuietBackgroundProcesses.UI.Views.QuietBackgroundProcessesPage",
+ "viewModelFullName": "DevHome.QuietBackgroundProcesses.UI.ViewModels.QuietBackgroundProcessesViewModel",
+ "icon": "f5b0",
+ "experimentalFeatureIdentity": "QuietBackgroundProcessesExperiment"
}
]
}
@@ -79,6 +87,27 @@
"visible": false
}
]
+ },
+ {
+ "identity": "QuietBackgroundProcessesExperiment",
+ "enabledByDefault": false,
+ "buildTypeOverrides": [
+ {
+ "buildType": "dev",
+ "enabledByDefault": false,
+ "visible": true
+ },
+ {
+ "buildType": "canary",
+ "enabledByDefault": false,
+ "visible": false
+ },
+ {
+ "buildType": "release",
+ "enabledByDefault": false,
+ "visible": false
+ }
+ ]
}
]
}
diff --git a/src/Package.appxmanifest b/src/Package.appxmanifest
index 9fccbea3e8..49ef44fb3e 100644
--- a/src/Package.appxmanifest
+++ b/src/Package.appxmanifest
@@ -1,5 +1,5 @@
-
+
@@ -8,6 +8,22 @@
+
+
+
+ DevHome.QuietBackgroundProcesses.Server.exe
+ singleInstance
+
+
+
+
+
+
+ DevHome.QuietBackgroundProcesses.ElevatedServer.exe
+ singleInstance
+
+
+
diff --git a/test/DevHome.Test.csproj b/test/DevHome.Test.csproj
index 08396c0ef9..2dc7b91664 100644
--- a/test/DevHome.Test.csproj
+++ b/test/DevHome.Test.csproj
@@ -1,5 +1,5 @@
-
+
DevHome.Test
x86;x64;arm64
diff --git a/tools/Dashboard/DevHome.Dashboard.UnitTest/DevHome.Dashboard.UnitTest.csproj b/tools/Dashboard/DevHome.Dashboard.UnitTest/DevHome.Dashboard.UnitTest.csproj
index ccf2b90e3a..dade52d4e8 100644
--- a/tools/Dashboard/DevHome.Dashboard.UnitTest/DevHome.Dashboard.UnitTest.csproj
+++ b/tools/Dashboard/DevHome.Dashboard.UnitTest/DevHome.Dashboard.UnitTest.csproj
@@ -1,5 +1,5 @@
-
+
Dashboard.Test
x86;x64;arm64
diff --git a/tools/Experiments/src/DevHome.Experiments.csproj b/tools/Experiments/src/DevHome.Experiments.csproj
index 461a8c3b2c..7dc9b769da 100644
--- a/tools/Experiments/src/DevHome.Experiments.csproj
+++ b/tools/Experiments/src/DevHome.Experiments.csproj
@@ -1,5 +1,5 @@
-
+
DevHome.Experiments
x86;x64;arm64
@@ -12,6 +12,7 @@
+
diff --git a/tools/Experiments/src/Strings/en-us/Resources.resw b/tools/Experiments/src/Strings/en-us/Resources.resw
index 02a5ec5771..18553d4f5e 100644
--- a/tools/Experiments/src/Strings/en-us/Resources.resw
+++ b/tools/Experiments/src/Strings/en-us/Resources.resw
@@ -1,69 +1,69 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- This is a test experiment page
- The name is Experiments
-
-
- Test Experiment page
- The name of the Experiments page
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ This is a test experiment page
+ The name is Experiments
+
+
+ Test Experiment page
+ The name of the Experiments page
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/.gitattributes b/tools/QuietBackgroundProcesses/.gitattributes
new file mode 100644
index 0000000000..5dbd6676cc
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/.gitattributes
@@ -0,0 +1,3 @@
+# Set default behavior to automatically normalize line endings.
+
+* text=crlf
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj
new file mode 100644
index 0000000000..9e1e35bf1c
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj
@@ -0,0 +1,195 @@
+
+
+
+ C++
+
+
+
+
+ true
+ true
+ true
+ true
+ {4B370E2F-FB1D-4887-90BF-3B72517485CE}
+ DevHome.QuietBackgroundProcesses.Common
+ DevHome.QuietBackgroundProcesses
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.22000.0
+ 10.0.17134.0
+ false
+ AnyCPU\$(Configuration)\Merged\
+ $(CppOutDir)
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ StaticLibrary
+ v143
+ v142
+ v141
+ v140
+ Unicode
+ false
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ NotUsing
+
+
+
+
+ Level4
+ %(AdditionalOptions) /bigobj
+ _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)
+
+
+ Windows
+ false
+
+
+
+
+
+
+ stdcpp17
+ %(AdditionalIncludeDirectories)
+
+
+ onecore.lib;%(AdditionalDependencies)
+
+
+
+
+ %(Filename).h
+ $(ProjectDir)$(GeneratedFilesDir)midl
+ $(ProjectDir)$(GeneratedFilesDir)winmd\%(Filename).winmd
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ Disabled
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MdmergeInputs Include="@(Midl)" Condition="'%(Midl.ExcludedFromBuild)' != 'true'">
+ %(Midl.MetadataFileName)
+
+
+
+
+ AnyCPU\$(Configuration)\Merged\
+ -n:2
+ -v
+ $(MdmergeParameters) -metadata_dir "$(WindowsSDK_MetadataFoundationPath)"
+ $(MdmergeParameters) @(MdmergeInputs->'-i "%(Identity)"', '
+')
+ $(MdmergeParameters) -o "$(MdmergeMergedDir.TrimEnd('\'))" -partial $(MdmergeMergeDepth)
+
+
+ $(MdmergeMergedDir)DevHome.QuietBackgroundProcesses.winmd
+ $(IntDir)$(MSBuildProjectFile).mdmerge.rsp
+ $(MdMergePath)mdmerge %40"$(MdmergeResponseFile)"
+
+
+
+
+
+
+
+
+ copy /Y "$(MdmergeMergedDir)DevHome.QuietBackgroundProcesses.winmd" "$(OutDir)."
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl
new file mode 100644
index 0000000000..c64cb8d568
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl
@@ -0,0 +1,25 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+import "inspectable.idl";
+
+namespace DevHome.QuietBackgroundProcesses
+{
+ [default_interface]
+ runtimeclass QuietBackgroundProcessesSession
+ {
+ static QuietBackgroundProcessesSession GetSingleton();
+ Int64 Start();
+ void Stop();
+ Boolean IsActive { get; };
+ Int64 TimeLeftInSeconds { get; };
+ }
+
+ [default_interface]
+ runtimeclass QuietBackgroundProcessesSessionManager {
+ QuietBackgroundProcessesSessionManager();
+ static Boolean IsFeaturePresent();
+ static QuietBackgroundProcessesSession GetSession();
+ static QuietBackgroundProcessesSession TryGetSession();
+ }
+}
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props
new file mode 100644
index 0000000000..e34141b019
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h
new file mode 100644
index 0000000000..9b42fa2fad
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h
@@ -0,0 +1,140 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+constexpr bool DEBUG_BUILD =
+#if _DEBUG
+ true;
+#else
+ false;
+#endif
+
+template
+struct wrl_module_object_ref
+{
+ struct details
+ {
+ static void wrl_decrement_object_count()
+ {
+ auto& module = T::GetModule();
+ auto count = module.DecrementObjectCount();
+ auto msg = std::wstring(L"WRL: DecrementObjectCount = ") + std::to_wstring(count) + std::wstring(L"\n");
+ OutputDebugStringW(msg.c_str());
+ }
+ };
+
+ using wrl_module_object_ref_releaser = wil::unique_call;
+
+ wrl_module_object_ref()
+ {
+ auto& module = T::GetModule();
+ auto count = module.IncrementObjectCount();
+ auto msg = std::wstring(L"WRL: IncrementObjectCount = ") + std::to_wstring(count) + std::wstring(L"\n");
+ OutputDebugStringW(msg.c_str());
+
+ m_moduleReference.activate();
+ }
+
+ wrl_module_object_ref(wrl_module_object_ref&& other) noexcept = default;
+ wrl_module_object_ref& operator=(wrl_module_object_ref&& other) noexcept = default;
+
+ wrl_module_object_ref(const wrl_module_object_ref&) = delete;
+ wrl_module_object_ref& operator=(const wrl_module_object_ref&) = delete;
+
+ void reset()
+ {
+ m_moduleReference.reset();
+ }
+
+private:
+
+ wrl_module_object_ref_releaser m_moduleReference{ false };
+};
+
+using wrl_server_process_ref = wrl_module_object_ref>;
+
+inline std::optional try_get_registry_value_dword(HKEY key, _In_opt_ PCWSTR subKey, _In_opt_ PCWSTR value_name, ::wil::reg::key_access access = ::wil::reg::key_access::read)
+{
+ wil::unique_hkey hkey;
+ if (SUCCEEDED(wil::reg::open_unique_key_nothrow(key, subKey, hkey, access)))
+ {
+ if (auto keyvalue = wil::reg::try_get_value_dword(hkey.get(), value_name))
+ {
+ return keyvalue.value();
+ }
+ }
+ return std::nullopt;
+}
+
+inline void WaitForDebuggerIfPresent()
+{
+ auto waitForDebugger = try_get_registry_value_dword(HKEY_LOCAL_MACHINE, LR"(Software\Microsoft\Windows\CurrentVersion\DevHome\QuietBackgroundProcesses)", L"WaitForDebugger");
+
+ if (waitForDebugger.value_or(0))
+ {
+ while (!IsDebuggerPresent())
+ {
+ Sleep(1000);
+ };
+ DebugBreak();
+ }
+}
+
+inline bool IsTokenElevated(HANDLE token)
+{
+ auto mandatoryLabel = wil::get_token_information(token);
+ LONG levelRid = static_cast(mandatoryLabel->Label.Sid)->SubAuthority[0];
+ return levelRid == SECURITY_MANDATORY_HIGH_RID;
+}
+
+inline void SelfElevate(std::optional const& arguments)
+{
+ auto path = wil::GetModuleFileNameW();
+
+ SHELLEXECUTEINFO sei = { sizeof(sei) };
+ sei.lpVerb = L"runas";
+ sei.lpFile = path.get();
+ sei.lpParameters = arguments.value().c_str();
+ sei.hwnd = NULL;
+ sei.nShow = SW_NORMAL;
+
+ THROW_LAST_ERROR_IF(!ShellExecuteEx(&sei));
+}
+
+inline std::wstring ParseServerNameArgument(std::wstring_view wargv)
+{
+ constexpr wchar_t serverNamePrefix[] = L"-ServerName:";
+ if (_wcsnicmp(wargv.data(), serverNamePrefix, wcslen(serverNamePrefix)) != 0)
+ {
+ THROW_HR(E_UNEXPECTED);
+ }
+ return { wargv.data() + wcslen(serverNamePrefix) };
+}
+
+inline void SetComFastRundownAndNoEhHandle()
+{
+ // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously.
+ wil::com_ptr pGlobalOptions;
+ THROW_IF_FAILED(CoCreateInstance(CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGlobalOptions)));
+ THROW_IF_FAILED(pGlobalOptions->Set(COMGLB_RO_SETTINGS, COMGLB_FAST_RUNDOWN));
+ THROW_IF_FAILED(pGlobalOptions->Set(COMGLB_EXCEPTION_HANDLING, COMGLB_EXCEPTION_DONOT_HANDLE_ANY));
+}
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/empty.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/empty.cpp
new file mode 100644
index 0000000000..2c3629c084
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/empty.cpp
@@ -0,0 +1,5 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+// A cpp is required to produce a .lib, and a .lib is required to exist if this project is
+// referenced by another cpp project.
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj
new file mode 100644
index 0000000000..f1922205f0
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+ enable
+ enable
+ $(CppBaseOutDir)\DevHome.QuietBackgroundProcesses.Common\
+
+
+
+
+ 10.0.19041.0
+ DevHome.QuietBackgroundProcesses
+ $(OutDir)
+
+
+
+ $(OutDir)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj
new file mode 100644
index 0000000000..1dfb5c237d
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj
@@ -0,0 +1,173 @@
+
+
+
+ C++
+
+
+
+
+
+ true
+ true
+ true
+ true
+ {75945141-03ac-4c40-a586-16d463a0ac1b}
+ DevHome.QuietBackgroundProcesses.ElevatedServer
+ DevHome.QuietBackgroundProcesses
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.22000.0
+ 10.0.17134.0
+ false
+ true
+ $(CppOutDir)
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ $(CppOutDir)
+
+
+ Application
+ v143
+ v142
+ v141
+ v140
+ Unicode
+ false
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)
+
+
+ Windows
+ false
+
+
+
+
+
+
+ stdcpp17
+ $(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\$(GeneratedFilesDir)midl;%(AdditionalIncludeDirectories)
+
+
+ onecore.lib;%(AdditionalDependencies)
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ Disabled
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+ {4b370e2f-fb1d-4887-90bf-3b72517485ce}
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props
new file mode 100644
index 0000000000..e34141b019
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp
new file mode 100644
index 0000000000..fbd08ff74a
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp
@@ -0,0 +1,136 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "TimedQuietSession.h"
+
+#include "DevHome.QuietBackgroundProcesses.h"
+
+constexpr auto DEFAULT_QUIET_DURATION = std::chrono::hours(2);
+
+std::mutex g_mutex;
+std::unique_ptr g_activeTimer;
+
+namespace ABI::DevHome::QuietBackgroundProcesses
+{
+ class QuietBackgroundProcessesSession :
+ public Microsoft::WRL::RuntimeClass<
+ Microsoft::WRL::RuntimeClassFlags,
+ IQuietBackgroundProcessesSession,
+ Microsoft::WRL::FtmBase>
+ {
+ InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession, BaseTrust);
+
+ public:
+ STDMETHODIMP RuntimeClassInitialize() noexcept
+ {
+ return S_OK;
+ }
+
+ // IQuietBackgroundProcessesSession
+ STDMETHODIMP Start(__int64* result) noexcept override try
+ {
+ auto lock = std::scoped_lock(g_mutex);
+
+ // Stop and discard the previous timer
+ if (g_activeTimer)
+ {
+ g_activeTimer->Cancel();
+ }
+
+ std::chrono::seconds duration = DEFAULT_QUIET_DURATION;
+ if (auto durationOverride = try_get_registry_value_dword(HKEY_LOCAL_MACHINE, LR"(Software\Microsoft\Windows\CurrentVersion\DevHome\QuietBackgroundProcesses)", L"Duration"))
+ {
+ duration = std::chrono::seconds(durationOverride.value());
+ }
+
+ // Start timer
+ g_activeTimer.reset(new TimedQuietSession(duration));
+
+ // Return duration for showing countdown
+ *result = g_activeTimer->TimeLeftInSeconds();
+ return S_OK;
+ }
+ CATCH_RETURN()
+
+ STDMETHODIMP Stop() noexcept override try
+ {
+ auto lock = std::scoped_lock(g_mutex);
+
+ // Turn off quiet mode and cancel timer
+ if (g_activeTimer)
+ {
+ g_activeTimer->Cancel();
+ g_activeTimer.reset();
+ }
+
+ return S_OK;
+ }
+ CATCH_RETURN()
+
+ STDMETHODIMP get_IsActive(::boolean* value) noexcept override try
+ {
+ auto lock = std::scoped_lock(g_mutex);
+ *value = false;
+ if (g_activeTimer)
+ {
+ *value = g_activeTimer->IsActive();
+ }
+ return S_OK;
+ }
+ CATCH_RETURN()
+
+ STDMETHODIMP get_TimeLeftInSeconds(__int64* value) noexcept override try
+ {
+ auto lock = std::scoped_lock(g_mutex);
+ *value = 0;
+ if (g_activeTimer)
+ {
+ *value = g_activeTimer->TimeLeftInSeconds();
+ }
+ return S_OK;
+ }
+ CATCH_RETURN()
+ };
+
+ class QuietBackgroundProcessesSessionStatics WrlFinal :
+ public Microsoft::WRL::AgileActivationFactory<
+ Microsoft::WRL::Implements>
+ {
+ InspectableClassStatic(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession, BaseTrust);
+
+ public:
+ STDMETHODIMP ActivateInstance(_COM_Outptr_ IInspectable**) noexcept
+ {
+ // Disallow activation - must use GetSingleton()
+ return E_NOTIMPL;
+ }
+
+ // IQuietBackgroundProcessesSessionStatics
+ STDMETHODIMP GetSingleton(_COM_Outptr_ IQuietBackgroundProcessesSession** session) noexcept override try
+ {
+ // Instanced objects are the only feasible way to manage a COM singleton without keeping a strong
+ // handle to the server - which keeps it alive. (IWeakReference keeps a strong handle to the server!)
+ // An 'instance' can be thought of as a 'handle' to 'the singleton' backend.
+ THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(session));
+ return S_OK;
+ }
+ CATCH_RETURN()
+ };
+
+ ActivatableClassWithFactory(QuietBackgroundProcessesSession, QuietBackgroundProcessesSessionStatics);
+}
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp
new file mode 100644
index 0000000000..b6a6fbf14d
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#include "pch.h"
+
+#include
+
+#include
+#include "QuietState.h"
+
+namespace QuietState
+{
+ std::mutex g_mutex;
+
+ void TurnOff() noexcept
+ {
+ auto lock = std::scoped_lock(g_mutex);
+ LOG_IF_FAILED(DisableQuietBackgroundProcesses());
+ }
+
+ unique_quietwindowclose_call TurnOn()
+ {
+ auto lock = std::scoped_lock(g_mutex);
+ THROW_IF_FAILED(EnableQuietBackgroundProcesses());
+ return unique_quietwindowclose_call{};
+ }
+}
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h
new file mode 100644
index 0000000000..92ac8855c7
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft Corporation and Contributors
+// Licensed under the MIT license.
+
+#pragma once
+
+#include
+
+namespace QuietState
+{
+ void TurnOff() noexcept;
+
+ using unique_quietwindowclose_call = wil::unique_call;
+
+ unique_quietwindowclose_call TurnOn();
+}
+
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h
new file mode 100644
index 0000000000..3dcc157e69
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h
@@ -0,0 +1,143 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "DevHome.QuietBackgroundProcesses.h"
+
+#include "Timer.h"
+#include "QuietState.h"
+
+using ElevatedServerReference = wrl_server_process_ref;
+
+struct UnelevatedServerReference
+{
+ wil::com_ptr m_reference;
+
+ UnelevatedServerReference() :
+ m_reference(wil::GetActivationFactory(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager))
+ {
+ }
+
+ void reset()
+ {
+ m_reference.reset();
+ }
+};
+
+
+// TimedQuietSession is a 2 hour "Quiet Background Processes" timed window that disables quiet
+// mode when the timer expires or when explicitly cancelled. It keeps also keeps the server alive.
+//
+// TimedQuietSession maintains,
+// 1. quiet mode signal
+// 2. session timer
+// 3. handle to session (elevated) server
+// 4. handle to manager (unelevated) server
+//
+// COM server lifetime & process interaction:
+//
+// Processes:
+// DevHome (client) -> UnelevatedServer (manager) -> ElevatedServer (session)
+//
+// Manager (unelevated server):
+// Role of manager is simply allow client to check if session (elevated server) is alive
+// without risking launching a UAC prompt. It caches a com proxy interface to session.
+//
+// Session (elevated server):
+// Role of session is to enable/disable quiet mode and keep a timer.
+//
+// Lifetime:
+// - The manager and session keep each other alive.
+//
+// - The session (TimedQuietSession) runs in ElevatedServer and keeps this elevated server
+// alive until timer expiration.
+//
+// - The session (TimedQuietSession) also keeps the manager (in unelevated server) alive until timer expiration;
+// this is only because the manager caches a *strong* handle to the session (elevated server),
+// and there is no way to invalidate the session (proxy handle) in the client if we tore down
+// this session. (Using IWeakReference does hold a weak reference to the object, but also holds a strong
+// reference against the hosting process's lifetime.)
+//
+// Teardown Sequence:
+// When all session timers (elevated) expire, the manager (unelevated) reference is released -> COM triggers
+// teardown in unelevated server (assuming DevHome is closed), releasing the cached *strong* reference
+// to the session (elevated) -> COM triggers teardown in elevated server.
+//
+struct TimedQuietSession
+{
+ TimedQuietSession(std::chrono::seconds seconds)
+ {
+ m_timer = std::make_unique(seconds, [this]() {
+ auto lock = std::scoped_lock(m_mutex);
+ Deactivate();
+ });
+
+ // Turn on quiet mode
+ m_quietState = QuietState::TurnOn();
+ }
+
+ TimedQuietSession(TimedQuietSession&& other) noexcept = default;
+ TimedQuietSession& operator=(TimedQuietSession&& other) noexcept = default;
+
+ TimedQuietSession(const TimedQuietSession&) = delete;
+ TimedQuietSession& operator=(const TimedQuietSession&) = delete;
+
+ int64_t TimeLeftInSeconds()
+ {
+ auto lock = std::scoped_lock(m_mutex);
+ return m_timer->TimeLeftInSeconds();
+ }
+
+ bool IsActive()
+ {
+ auto lock = std::scoped_lock(m_mutex);
+ return (bool)m_quietState;
+ }
+
+ void Cancel()
+ {
+ auto lock = std::scoped_lock(m_mutex);
+
+ Deactivate();
+ m_timer->Cancel();
+
+ // Destruct timer on another thread because it's destructor is blocking
+ auto destructionThread = std::thread([timer = std::move(m_timer)]() {
+ // destruct timer here
+ });
+
+ destructionThread.detach();
+ }
+
+private:
+ void Deactivate()
+ {
+ // Turn off quiet mode
+ m_quietState.reset();
+
+ // Release lifetime handles to this elevated server and unelevated client server
+ m_unelevatedServer.reset();
+ m_elevatedServer.reset();
+ }
+
+ UnelevatedServerReference m_unelevatedServer; // Manager server
+ ElevatedServerReference m_elevatedServer; // Session server (this server)
+
+ QuietState::unique_quietwindowclose_call m_quietState{ false };
+ std::unique_ptr m_timer;
+ std::mutex m_mutex;
+};
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h
new file mode 100644
index 0000000000..f65699da0d
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h
@@ -0,0 +1,114 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include "pch.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "Utility.h"
+
+#if _DEBUG || NDEBUG
+#define TRACK_SECONDS_LEFT
+#endif
+
+class Timer
+{
+public:
+ Timer(std::chrono::seconds seconds, std::function callback) :
+ m_callback(std::forward>(callback)),
+ m_startTime(std::chrono::steady_clock::now()),
+ m_duration(seconds),
+ m_timerThread(std::thread(&Timer::TimerThread, this))
+ {
+ }
+
+ Timer(Timer&& other) noexcept = default;
+ Timer& operator=(Timer&& other) noexcept = default;
+
+ Timer(const Timer&) = delete;
+ Timer& operator=(const Timer&) = delete;
+
+ ~Timer()
+ {
+ if (m_timerThread.joinable())
+ {
+ m_timerThread.join();
+ }
+ }
+
+ void Cancel()
+ {
+ OutputDebugStringW(L"Timer: Cancelling\n");
+
+ auto lock = std::scoped_lock(m_mutex);
+
+ // Disable the callback from being called...
+ m_cancelled = true;
+
+ // ... wake up the timer thread.
+ m_cancelCondition.notify_one();
+ }
+
+ int64_t TimeLeftInSeconds()
+ {
+ auto lock = std::scoped_lock(m_mutex);
+ if (m_cancelled)
+ {
+ return 0;
+ }
+
+ auto secondsLeft = CalculateSecondsLeft();
+ return std::max(secondsLeft, 0ll);
+ }
+
+private:
+ int64_t CalculateSecondsLeft()
+ {
+ auto now = std::chrono::steady_clock::now();
+ auto elapsed = std::chrono::duration_cast(now - m_startTime);
+ auto secondsLeft = m_duration.count() - elapsed.count();
+#ifdef TRACK_SECONDS_LEFT
+ m_secondsLeft = secondsLeft;
+#endif
+ return secondsLeft;
+ }
+
+ void TimerThread()
+ {
+ // Pause until timer expired or cancelled
+ auto lock = std::unique_lock(m_mutex);
+
+ m_cancelCondition.wait_for(lock, m_duration, [this] {
+ return this->m_cancelled;
+ });
+
+ // Do the callback
+ if (!this->m_cancelled)
+ {
+ this->m_callback();
+ }
+
+ OutputDebugStringW(L"Timer: Finished\n");
+ }
+
+ std::chrono::steady_clock::time_point m_startTime{};
+ std::chrono::seconds m_duration{};
+ std::thread m_timerThread;
+ std::mutex m_mutex;
+ bool m_cancelled{};
+ std::condition_variable m_cancelCondition;
+ std::function m_callback;
+
+#ifdef TRACK_SECONDS_LEFT
+ int64_t m_secondsLeft = -1;
+#endif
+};
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp
new file mode 100644
index 0000000000..067085996e
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp
@@ -0,0 +1,109 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "Utility.h"
+#include "TimedQuietSession.h"
+#include "QuietState.h"
+
+int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR wargv, int wargc) try
+{
+ constexpr auto ELEVATED_SERVER_STARTED_EVENT_NAME = L"Global\\DevHome_QuietBackgroundProcesses_ElevatedServer_Started";
+
+ if (wargc < 1)
+ {
+ THROW_HR(E_INVALIDARG);
+ }
+
+ // Parse the servername from the cmdline argument, e.g. "-ServerName:DevHome.QuietBackgroundProcesses.ElevatedServer"
+ auto serverName = ParseServerNameArgument(wargv);
+
+ if (wil::compare_string_ordinal(serverName, L"DevHome.QuietBackgroundProcesses.ElevatedServer", true) != 0)
+ {
+ THROW_HR(E_INVALIDARG);
+ }
+
+ // Let's self-elevate and terminate
+ if (!IsTokenElevated(GetCurrentProcessToken()))
+ {
+ wil::unique_event elevatedServerRunningEvent;
+ elevatedServerRunningEvent.create(wil::EventOptions::ManualReset, ELEVATED_SERVER_STARTED_EVENT_NAME);
+
+ // Launch elevated instance
+ SelfElevate(wargv);
+
+ // Wait for the *actual* elevated server instance to register its winrt classes with COM before shutting down
+ elevatedServerRunningEvent.wait();
+ return 0;
+ }
+
+ WaitForDebuggerIfPresent();
+
+ auto unique_rouninitialize_call = wil::RoInitialize();
+
+ // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously.
+ SetComFastRundownAndNoEhHandle();
+
+ // To be safe, force quiet mode off to begin the proceedings in case we leaked the machine state previously
+ QuietState::TurnOff();
+
+ std::mutex mutex;
+ bool comFinished{};
+ std::condition_variable finishCondition;
+
+#pragma warning(push)
+#pragma warning(disable : 4324) // Avoid WRL alignment warning
+
+ // Register WRL callback when all objects are destroyed
+ auto& module = Microsoft::WRL::Module::Create([&] {
+ // The last instance object of the module is released
+ {
+ auto lock = std::unique_lock(mutex);
+ comFinished = true;
+ }
+ finishCondition.notify_one();
+ });
+
+#pragma warning(pop)
+
+ // Register WinRT activatable classes
+ module.RegisterObjects();
+ auto unique_wrl_registration_cookie = wil::scope_exit([&module]() {
+ module.UnregisterObjects();
+ });
+
+ // Tell the unelevated server instance that we've registered our winrt classes with COM (so it can terminate)
+ wil::unique_event elevatedServerRunningEvent;
+ elevatedServerRunningEvent.open(ELEVATED_SERVER_STARTED_EVENT_NAME);
+ elevatedServerRunningEvent.SetEvent();
+
+ // Wait for all server references to release (implicitly also waiting for timers to finish via CoAddRefServerProcess)
+ auto lock = std::unique_lock(mutex);
+
+ finishCondition.wait(lock, [&] {
+ return comFinished;
+ });
+
+ // Safety
+ QuietState::TurnOff();
+
+ return 0;
+}
+CATCH_RETURN()
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config
new file mode 100644
index 0000000000..42b20a75de
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp
new file mode 100644
index 0000000000..d58e93e60c
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation and Contributors
+// Licensed under the MIT license.
+
+#include "pch.h"
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h
new file mode 100644
index 0000000000..601ace8be4
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation and Contributors
+// Licensed under the MIT license.
+
+#pragma once
+
+#define NOMINMAX
+
+#include
+#include
+#include
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj
new file mode 100644
index 0000000000..492cee0113
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj
@@ -0,0 +1,175 @@
+
+
+
+ C++
+
+
+
+
+
+ true
+ true
+ true
+ true
+ {80805B43-CE75-4C6E-92F8-F385C1039E53}
+ DevHome.QuietBackgroundProcesses.Server
+ DevHome.QuietBackgroundProcesses
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0
+ 10.0.22000.0
+ 10.0.17134.0
+ false
+ $(CppOutDir)
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ Application
+ v143
+ v142
+ v141
+ v140
+ Unicode
+ false
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Use
+ pch.h
+ $(IntDir)pch.pch
+ Level4
+ %(AdditionalOptions) /bigobj
+ _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions)
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+
+
+ Windows
+ false
+
+
+
+
+
+
+ stdcpp17
+ C++
+ $(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\$(GeneratedFilesDir)midl;%(AdditionalIncludeDirectories)
+
+
+ onecore.lib;%(AdditionalDependencies)
+
+
+ %(Filename).h
+ $(ProjectDir)$(GeneratedFilesDir)midl
+ $(ProjectDir)$(GeneratedFilesDir)winmd\%(Filename).winmd
+
+
+
+
+ _DEBUG;%(PreprocessorDefinitions)
+ Disabled
+
+
+
+
+ NDEBUG;%(PreprocessorDefinitions)
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+ Create
+
+
+
+
+
+
+
+
+
+
+
+ {4b370e2f-fb1d-4887-90bf-3b72517485ce}
+
+
+
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props
new file mode 100644
index 0000000000..e34141b019
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp
new file mode 100644
index 0000000000..8f5a76b7cd
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include "DevHome.QuietBackgroundProcesses.h"
+
+namespace ABI::DevHome::QuietBackgroundProcesses
+{
+ class QuietBackgroundProcessesSessionManager :
+ public Microsoft::WRL::RuntimeClass<
+ Microsoft::WRL::RuntimeClassFlags,
+ IQuietBackgroundProcessesSessionManager,
+ Microsoft::WRL::FtmBase>
+ {
+ InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager, BaseTrust);
+
+ public:
+ STDMETHODIMP RuntimeClassInitialize() noexcept
+ {
+ return S_OK;
+ }
+ };
+
+ class QuietBackgroundProcessesSessionManagerStatics WrlFinal :
+ public Microsoft::WRL::AgileActivationFactory<
+ Microsoft::WRL::Implements>
+ {
+ InspectableClassStatic(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager, BaseTrust);
+
+ public:
+ // IActivationFactory method
+ STDMETHODIMP ActivateInstance(_Outptr_result_nullonfailure_ IInspectable** ppvObject) noexcept
+ try
+ {
+ THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(ppvObject));
+ return S_OK;
+ }
+ CATCH_RETURN()
+
+ // IQuietBackgroundProcessesSessionManagerStatics
+ STDMETHODIMP IsFeaturePresent(_Out_ boolean* isPresent) noexcept override try
+ {
+ THROW_IF_FAILED(IsQuietBackgroundProcessesFeaturePresent((bool*)isPresent));
+ return S_OK;
+ }
+ CATCH_RETURN();
+
+ STDMETHODIMP GetSession(_Outptr_result_nullonfailure_ IQuietBackgroundProcessesSession** session) noexcept override
+ try
+ {
+ auto lock = std::scoped_lock(m_mutex);
+ *session = nullptr;
+
+ if (!m_sessionReference)
+ {
+ auto factory = wil::GetActivationFactory(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession);
+ THROW_IF_FAILED(factory->GetSingleton(&m_sessionReference));
+ }
+ m_sessionReference.copy_to(session);
+ return S_OK;
+ }
+ CATCH_RETURN()
+
+ STDMETHODIMP TryGetSession(_COM_Outptr_result_maybenull_ IQuietBackgroundProcessesSession** session) noexcept override try
+ {
+ auto lock = std::scoped_lock(m_mutex);
+ m_sessionReference.try_copy_to(session);
+ return S_OK;
+ }
+ CATCH_RETURN()
+
+ private:
+ std::mutex m_mutex;
+ wil::com_ptr m_sessionReference;
+ };
+
+ ActivatableClassWithFactory(QuietBackgroundProcessesSessionManager, QuietBackgroundProcessesSessionManagerStatics);
+}
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp
new file mode 100644
index 0000000000..54ae2b766b
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp
@@ -0,0 +1,80 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "Utility.h"
+
+int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR wargv, int wargc) try
+{
+ WaitForDebuggerIfPresent();
+
+ if (wargc < 1)
+ {
+ THROW_HR(E_INVALIDARG);
+ }
+
+ // Parse the servername from the cmdline argument, e.g. "-ServerName:DevHome.QuietBackgroundProcesses.Server"
+ auto serverName = ParseServerNameArgument(wargv);
+
+ if (wil::compare_string_ordinal(serverName, L"DevHome.QuietBackgroundProcesses.Server", true) != 0)
+ {
+ THROW_HR(E_INVALIDARG);
+ }
+
+ auto unique_rouninitialize_call = wil::RoInitialize();
+
+ // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously.
+ SetComFastRundownAndNoEhHandle();
+
+ std::mutex mutex;
+ bool comFinished{};
+ std::condition_variable finishCondition;
+
+#pragma warning(push)
+#pragma warning(disable: 4324) // Avoid WRL alignment warning
+
+ // Register WRL callback when all objects are destroyed
+ auto& module = Microsoft::WRL::Module::Create([&] {
+ // The last instance object of the module is released
+ {
+ auto lock = std::unique_lock(mutex);
+ comFinished = true;
+ }
+ finishCondition.notify_one();
+ });
+
+#pragma warning(pop)
+
+ // Register WinRT activatable classes
+ module.RegisterObjects();
+ auto unique_wrl_registration_cookie = wil::scope_exit([&module]() {
+ module.UnregisterObjects();
+ });
+
+ // Wait for all server references to release
+ auto lock = std::unique_lock(mutex);
+
+ finishCondition.wait(lock, [&] {
+ return comFinished;
+ });
+
+ return 0;
+}
+CATCH_RETURN()
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config
new file mode 100644
index 0000000000..28332c3d1a
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp
new file mode 100644
index 0000000000..40e691ba78
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#include "pch.h"
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h
new file mode 100644
index 0000000000..9d6cb89293
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#pragma once
+
+#define NOMINMAX
+
+#include
+#include
+#include
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj
new file mode 100644
index 0000000000..2e8e6ecd31
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj
@@ -0,0 +1,22 @@
+
+
+
+ DevHome.QuietBackgroundProcesses.UI
+ x86;x64;arm64
+ win10-x86;win10-x64;win10-arm64
+ true
+
+
+
+
+
+
+
+
+
+
+
+ $(DefaultXamlRuntime)
+
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw
new file mode 100644
index 0000000000..bcc14801bd
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Quiet Background Processes
+ The name of the Quiet Background Processes page
+
+
+ Silence and track background processes that may hinder device performance
+ Description of the Quiet Background Processes feature
+
+
+ Quiet background processes
+ Inline title of the Quiet Background Processes feature
+
+
+ This feature can be activated for 2 hours.
+ A description of the Quiet Background Processes time window
+
+
+ Quiet background processes beta feature description
+ Title of the next settings card that explains the feature in more detail
+
+
+ Link to docs
+ Link that launches documentation
+
+
+ Provide feedback
+ Link that launches feedback
+
+
+ Related links
+ Label for the doc links
+
+
+
+
+ Feature not supported on this version of Windows
+ Indicates that this OS isn't new enough to support the feature
+
+
+ Session Error
+ Something went wrong when running the session
+
+
+ Session ended
+ The quiet session was cancelled or the time expired
+
+
+ Unable to cancel session
+ Something went wrong when cancelling the session
+
+
\ No newline at end of file
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs
new file mode 100644
index 0000000000..9387a34d2c
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs
@@ -0,0 +1,200 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+using DevHome.Common.Helpers;
+using DevHome.Common.Services;
+using Microsoft.UI.Xaml;
+
+namespace DevHome.QuietBackgroundProcesses.UI.ViewModels;
+
+public partial class QuietBackgroundProcessesViewModel : ObservableObject
+{
+ private readonly bool _isFeaturePresent;
+ private readonly TimeSpan _zero;
+#nullable enable
+ private DevHome.QuietBackgroundProcesses.QuietBackgroundProcessesSession? _session;
+#nullable disable
+
+ [ObservableProperty]
+ private string _sessionStateText;
+
+ private DevHome.QuietBackgroundProcesses.QuietBackgroundProcessesSession GetSession()
+ {
+ if (_session == null)
+ {
+ _session = QuietBackgroundProcessesSessionManager.GetSession();
+ }
+
+ return _session;
+ }
+
+ private string GetString(string id)
+ {
+ var stringResource = new StringResource("DevHome.QuietBackgroundProcesses.UI/Resources");
+ return stringResource.GetLocalized(id);
+ }
+
+ private string GetStatusString(string id)
+ {
+ return GetString("QuietBackgroundProcesses_Status_" + id);
+ }
+
+ public QuietBackgroundProcessesViewModel()
+ {
+ _zero = new TimeSpan(0, 0, 0);
+
+ _isFeaturePresent = DevHome.QuietBackgroundProcesses.QuietBackgroundProcessesSessionManager.IsFeaturePresent();
+ if (!_isFeaturePresent)
+ {
+ SessionStateText = GetStatusString("FeatureNotSupported");
+ return;
+ }
+
+ // Resume countdown if there's an existing quiet window
+ //
+ // Note: GetIsActive() won't ever launch a UAC prompt, but GetTimeRemaining() will if no session is running - so be careful with call order
+ if (GetIsActive())
+ {
+ _isToggleOn = true;
+ var timeLeftInSeconds = GetTimeRemaining();
+ StartCountdownTimer(timeLeftInSeconds);
+ }
+ }
+
+ public bool IsToggleEnabled => _isFeaturePresent;
+
+ private bool _isToggleOn;
+
+ public bool IsToggleOn
+ {
+ get => _isToggleOn;
+
+ set
+ {
+ if (_isToggleOn == value)
+ {
+ return;
+ }
+
+ _isToggleOn = value;
+
+ // Stop any existing timer
+ _dispatcherTimer?.Stop();
+
+ if (_isToggleOn)
+ {
+ try
+ {
+ // Launch the server, which then elevates itself, showing a UAC prompt
+ var timeLeftInSeconds = GetSession().Start();
+ StartCountdownTimer(timeLeftInSeconds);
+ }
+ catch (Exception ex)
+ {
+ SessionStateText = GetStatusString("SessionError");
+ Log.Logger()?.ReportError("QuietBackgroundProcessesSession::Start failed", ex);
+ }
+ }
+ else
+ {
+ try
+ {
+ GetSession().Stop();
+ SessionStateText = GetStatusString("SessionEnded");
+ }
+ catch (Exception ex)
+ {
+ SessionStateText = GetStatusString("UnableToCancelSession");
+ Log.Logger()?.ReportError("QuietBackgroundProcessesSession::Stop failed", ex);
+ }
+ }
+ }
+ }
+
+ private bool GetIsActive()
+ {
+ try
+ {
+ _session = DevHome.QuietBackgroundProcesses.QuietBackgroundProcessesSessionManager.TryGetSession();
+ if (_session != null)
+ {
+ return _session.IsActive;
+ }
+ }
+ catch (Exception ex)
+ {
+ SessionStateText = GetStatusString("SessionError");
+ Log.Logger()?.ReportError("QuietBackgroundProcessesSession::IsActive failed", ex);
+ }
+
+ return false;
+ }
+
+ private int GetTimeRemaining()
+ {
+ try
+ {
+ return (int)GetSession().TimeLeftInSeconds;
+ }
+ catch (Exception ex)
+ {
+ SessionStateText = GetStatusString("SessionError");
+ Log.Logger()?.ReportError("QuietBackgroundProcessesSession::TimeLeftInSeconds failed", ex);
+ return 0;
+ }
+ }
+
+ private DispatcherTimer _dispatcherTimer;
+ private TimeSpan _secondsLeft;
+
+ private void StartCountdownTimer(long timeLeftInSeconds)
+ {
+ if (timeLeftInSeconds <= 0)
+ {
+ return;
+ }
+
+ _dispatcherTimer = new DispatcherTimer();
+ _dispatcherTimer.Tick += DispatcherTimer_Tick;
+ _dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
+ _secondsLeft = new TimeSpan(0, 0, (int)timeLeftInSeconds);
+ _dispatcherTimer.Start();
+
+ SessionStateText = _secondsLeft.ToString();
+ }
+
+ private void DispatcherTimer_Tick(object sender, object e)
+ {
+ var sessionEnded = false;
+
+ _secondsLeft = new TimeSpan(0, 0, GetTimeRemaining());
+
+ if (_secondsLeft.CompareTo(_zero) <= 0)
+ {
+ // The window should be closed, but let's confirm with the server
+ if (GetSession().IsActive)
+ {
+ // There has been some drift
+ _secondsLeft = new TimeSpan(0, 0, GetTimeRemaining());
+ }
+ else
+ {
+ _dispatcherTimer.Stop();
+ _secondsLeft = _zero;
+ IsToggleOn = false;
+ sessionEnded = true;
+ }
+ }
+
+ if (sessionEnded)
+ {
+ SessionStateText = GetStatusString("SessionEnded");
+ }
+ else
+ {
+ SessionStateText = _secondsLeft.ToString(); // CultureInfo.InvariantCulture
+ }
+ }
+}
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml
new file mode 100644
index 0000000000..ffcdf746b4
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml.cs
new file mode 100644
index 0000000000..9f0fb77e41
--- /dev/null
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml.cs
@@ -0,0 +1,26 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using DevHome.Common;
+using DevHome.QuietBackgroundProcesses.UI.ViewModels;
+
+namespace DevHome.QuietBackgroundProcesses.UI.Views;
+
+///
+/// An empty page that can be used on its own or navigated to within a Frame.
+///
+public sealed partial class QuietBackgroundProcessesPage : ToolPage
+{
+ public override string ShortName => "Quiet Background Processes";
+
+ public QuietBackgroundProcessesViewModel ViewModel
+ {
+ get;
+ }
+
+ public QuietBackgroundProcessesPage()
+ {
+ ViewModel = new QuietBackgroundProcessesViewModel();
+ InitializeComponent();
+ }
+}
From 2ea4a98c8d8c96fe0d3683a65ad60a8a469ad487 Mon Sep 17 00:00:00 2001
From: subhasan
Date: Thu, 14 Mar 2024 13:15:07 -0700
Subject: [PATCH 003/121] Adding Telemetry to measure if users looks for more
Apps in app install list (#2410)
Co-authored-by: Subha Santhanam
---
.../DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs
index f3604806e5..bcf3d14b07 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageCatalogListViewModel.cs
@@ -14,6 +14,7 @@
using DevHome.SetupFlow.Behaviors;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Services;
+using DevHome.Telemetry;
using Microsoft.UI.Dispatching;
namespace DevHome.SetupFlow.ViewModels;
@@ -138,6 +139,7 @@ private void RemoveShimmers(int count)
[RelayCommand]
private void ViewAllPackages(PackageCatalogViewModel catalog)
{
+ TelemetryFactory.Get().LogCritical("Apps_ViewAll_Event");
AppManagementBehavior.SetHeaderVisibility(false);
ViewAllCatalog = catalog;
}
From db1ce51fdc0d4ff25c899e7f77023026c7329e61 Mon Sep 17 00:00:00 2001
From: Eric Johnson
Date: Fri, 15 Mar 2024 09:27:04 -0700
Subject: [PATCH 004/121] Fix experimental features visibility in nav menu
(#2420)
---
src/Views/ShellPage.xaml.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Views/ShellPage.xaml.cs b/src/Views/ShellPage.xaml.cs
index e8d7e875fe..6e4a690a6f 100644
--- a/src/Views/ShellPage.xaml.cs
+++ b/src/Views/ShellPage.xaml.cs
@@ -149,12 +149,12 @@ public void UpdateExperimentalPageState(ExperimentalFeature expFeature)
private void UpdateNavigationMenuItems()
{
- var expVM = App.Current.GetService();
+ var expService = App.Current.GetService();
foreach (var group in App.NavConfig.NavMenu.Groups)
{
foreach (var tool in group.Tools)
{
- var expFeature = expVM.ExperimentalFeatures.FirstOrDefault(x => x.Id == tool.ExperimentalFeatureIdentity);
+ var expFeature = expService.ExperimentalFeatures.FirstOrDefault(x => x.Id == tool.ExperimentalFeatureIdentity);
var navigationViewItemString = $@"
Date: Fri, 15 Mar 2024 14:19:20 -0700
Subject: [PATCH 005/121] Add telemetry for Page Next Source (#2413)
* 2412 Adding instrumentation to understand BAckup restore flow
* Updating file names
* Renaming Telemetry file to help better understand the scenario being tracked.
---------
Co-authored-by: Subha Santhanam
---
.../SetupFlow/PageNextSourceEvent.cs | 31 +++++++++++++++++++
.../ViewModels/SetupPageViewModelBase.cs | 3 ++
2 files changed, 34 insertions(+)
create mode 100644 common/TelemetryEvents/SetupFlow/PageNextSourceEvent.cs
diff --git a/common/TelemetryEvents/SetupFlow/PageNextSourceEvent.cs b/common/TelemetryEvents/SetupFlow/PageNextSourceEvent.cs
new file mode 100644
index 0000000000..ff1b0cd003
--- /dev/null
+++ b/common/TelemetryEvents/SetupFlow/PageNextSourceEvent.cs
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Diagnostics.Tracing;
+using DevHome.Telemetry;
+using Microsoft.Diagnostics.Telemetry;
+using Microsoft.Diagnostics.Telemetry.Internal;
+
+namespace DevHome.Common.TelemetryEvents.SetupFlow;
+
+[EventData]
+public class PageNextSourceEvent : EventBase
+{
+ public string NavigationTarget
+ {
+ get;
+ }
+
+ public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServiceUsage;
+
+ public PageNextSourceEvent(string navigationTarget)
+ {
+ NavigationTarget = navigationTarget;
+ }
+
+ public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings)
+ {
+ // No sensitive strings to replace.
+ }
+}
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupPageViewModelBase.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupPageViewModelBase.cs
index 20b1bdca83..4442a845e0 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupPageViewModelBase.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupPageViewModelBase.cs
@@ -4,8 +4,10 @@
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
+using DevHome.Common.TelemetryEvents.SetupFlow;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Services;
+using DevHome.Telemetry;
namespace DevHome.SetupFlow.ViewModels;
@@ -138,6 +140,7 @@ public async Task OnNavigateFromAsync()
{
_hasExecutedFirstNavigateFrom = true;
Log.Logger?.ReportInfo(Log.Component.Orchestrator, $"Executing pre-navigation tasks for page {this.GetType().Name}");
+ TelemetryFactory.Get().Log("PageNavigated", LogLevel.Critical, new PageNextSourceEvent(this.GetType().Name));
await OnFirstNavigateFromAsync();
}
}
From 7845c1ccfad7e7c49adc4cda70b86c357af80342 Mon Sep 17 00:00:00 2001
From: Kristen Schau <47155823+krschau@users.noreply.github.com>
Date: Mon, 18 Mar 2024 11:07:02 -0400
Subject: [PATCH 006/121] Provide API for registering nested pages (#2356)
---
common/Services/IPageService.cs | 17 ++++++++++++
docs/tools.md | 16 +++++-------
docs/tools/Dashboard.md | 14 ++++++++++
.../Extensions/PageExtensions.cs | 24 +++++++++++++++++
src/Contracts/Services/IPageService.cs | 9 -------
src/Services/NavigationService.cs | 1 -
src/Services/PageService.cs | 26 ++++++++-----------
.../Extensions/PageExtensions.cs | 16 ++++++++++++
8 files changed, 88 insertions(+), 35 deletions(-)
create mode 100644 common/Services/IPageService.cs
create mode 100644 docs/tools/Dashboard.md
create mode 100644 settings/DevHome.Settings/Extensions/PageExtensions.cs
delete mode 100644 src/Contracts/Services/IPageService.cs
create mode 100644 tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs
diff --git a/common/Services/IPageService.cs b/common/Services/IPageService.cs
new file mode 100644
index 0000000000..1354b09a31
--- /dev/null
+++ b/common/Services/IPageService.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using CommunityToolkit.Mvvm.ComponentModel;
+using Microsoft.UI.Xaml.Controls;
+
+namespace DevHome.Common.Services;
+
+public interface IPageService
+{
+ Type GetPageType(string key);
+
+ public void Configure()
+ where T_VM : ObservableObject
+ where T_V : Page;
+}
diff --git a/docs/tools.md b/docs/tools.md
index 3b0654215b..4768b49eed 100644
--- a/docs/tools.md
+++ b/docs/tools.md
@@ -42,7 +42,7 @@ The Dev Home framework will look at all types in its assembly for any inheriting
On a found type, the framework will use:
- ShortName property to get the name of the tool
-### Method definition
+#### Method definition
This section contains a more detailed description of each of the interface methods.
@@ -59,16 +59,12 @@ Returns the name of the tool. This is used for the navigation menu text.
[`toolpage.cs`](../common/ToolPage.cs)
Contains the interface definition for Dev Home tools.
-## Dashboard Tool
-The Dashboard page hosts and displays Windows Widgets. Widgets are small UI containers that display text and graphics, associated with an app installed on the device. For information on creating widgets, see [Widgets Overview](https://learn.microsoft.com/windows/apps/design/widgets/) and [Widget providers](https://learn.microsoft.com/windows/apps/develop/widgets/widget-providers).
+### Navigation
-Each widget is represented by a [`WidgetViewModel`](../tools/Dashboard/DevHome.Dashboard/ViewModels/WidgetViewModel.cs). The WidgetViewModel displays itself inside a [`WidgetControl`](../tools/Dashboard/DevHome.Dashboard/Controls/WidgetControl.xaml), and the WidgetControls are grouped into a [`WidgetBoard`](../tools/Dashboard/DevHome.Dashboard/Controls/WidgetBoard.cs).
+In order to allow navigation to your tool, your page and ViewModel must be registered with the PageService. If your tool only contains one page, it is automatically registered for you since you added your page to `NavConfig.jsonc`. However, you may have other sub-pages you wish to register.
-### Widget UI
+In order to do so, you must create an extension method for the PageService inside your tool. See examples in [Settings](../settings/DevHome.Settings/Extensions/PageExtensions.cs) or [Extensions](../tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs). Then, call your extension from the [PageService](../src/Services/PageService.cs).
-The Widget UI consists of two main parts. At the top, there is a context menu and an attribution area. For more information on these components, please read [Built-in widget UI components](https://learn.microsoft.com/windows/apps/design/widgets/widgets-states-and-ui#built-in-widget-ui-components). The rest of the widget content is an [Adaptive Card](https://learn.microsoft.com/windows/apps/design/widgets/widgets-create-a-template) provided by the [Widget Provider](https://learn.microsoft.com/windows/apps/develop/widgets/widget-providers).
+## Existing tools
-Widgets are rendered by Adaptive Cards, and there are a few ways Dev Home customizes the look and feel of the cards. Please note all of these are subject to change while Dev Home is in Preview.
-* Dev Home widgets use the [Adaptive Card schema](https://adaptivecards.io/explorer/) version 1.5, which is the most recent schema supported by the WinUI 3 Adaptive Card renderer.
-* There are [HostConfig](https://learn.microsoft.com/adaptive-cards/sdk/rendering-cards/uwp/host-config) files that define common styles (e.g., font family, font sizes, default spacing) and behaviors (e.g., max number of actions) for all the widgets. There is one for [light mode](../tools/Dashboard/DevHome.Dashboard/Assets/HostConfigLight.json) and one for [dark mode](../tools/Dashboard/DevHome.Dashboard/Assets/HostConfigDark.json).
-* Dev Home supports a custom AdaptiveElement type called [`LabelGroup`](../common/Renderers/LabelGroup.cs). This allows a card author to render a set of labels, each with a specified background color. For an example of how to use this type, please see the [GitHub Issues widget](https://github.com/microsoft/devhomegithubextension/blob/main/src/GitHubExtension/Widgets/Templates/GitHubIssuesTemplate.json).
+[Dashboard](./tools/Dashboard.md)
diff --git a/docs/tools/Dashboard.md b/docs/tools/Dashboard.md
new file mode 100644
index 0000000000..d6cc48f007
--- /dev/null
+++ b/docs/tools/Dashboard.md
@@ -0,0 +1,14 @@
+# Dashboard
+
+The Dashboard page hosts and displays Windows Widgets. Widgets are small UI containers that display text and graphics, associated with an app installed on the device. For information on creating widgets, see [Widgets Overview](https://learn.microsoft.com/windows/apps/design/widgets/) and [Widget providers](https://learn.microsoft.com/windows/apps/develop/widgets/widget-providers).
+
+Each widget is represented by a [`WidgetViewModel`](../tools/Dashboard/DevHome.Dashboard/ViewModels/WidgetViewModel.cs). The WidgetViewModel displays itself inside a [`WidgetControl`](../../tools/Dashboard/DevHome.Dashboard/Controls/WidgetControl.xaml), and the WidgetControls are grouped into a [`WidgetBoard`](../../tools/Dashboard/DevHome.Dashboard/Controls/WidgetBoard.cs).
+
+### Widget UI
+
+The Widget UI consists of two main parts. At the top, there is a context menu and an attribution area. For more information on these components, please read [Built-in widget UI components](https://learn.microsoft.com/windows/apps/design/widgets/widgets-states-and-ui#built-in-widget-ui-components). The rest of the widget content is an [Adaptive Card](https://learn.microsoft.com/windows/apps/design/widgets/widgets-create-a-template) provided by the [Widget Provider](https://learn.microsoft.com/windows/apps/develop/widgets/widget-providers).
+
+Widgets are rendered by Adaptive Cards, and there are a few ways Dev Home customizes the look and feel of the cards. Please note all of these are subject to change while Dev Home is in Preview.
+* Dev Home widgets use the [Adaptive Card schema](https://adaptivecards.io/explorer/) version 1.5, which is the most recent schema supported by the WinUI 3 Adaptive Card renderer.
+* There are [HostConfig](https://learn.microsoft.com/adaptive-cards/sdk/rendering-cards/uwp/host-config) files that define common styles (e.g., font family, font sizes, default spacing) and behaviors (e.g., max number of actions) for all the widgets. There is one for [light mode](../../tools/Dashboard/DevHome.Dashboard/Assets/HostConfigLight.json) and one for [dark mode](../tools/Dashboard/DevHome.Dashboard/Assets/HostConfigDark.json).
+* Dev Home supports a custom AdaptiveElement type called [`LabelGroup`](../../common/Renderers/LabelGroup.cs). This allows a card author to render a set of labels, each with a specified background color. For an example of how to use this type, please see the [GitHub Issues widget](https://github.com/microsoft/devhomegithubextension/blob/main/src/GitHubExtension/Widgets/Templates/GitHubIssuesTemplate.json).
diff --git a/settings/DevHome.Settings/Extensions/PageExtensions.cs b/settings/DevHome.Settings/Extensions/PageExtensions.cs
new file mode 100644
index 0000000000..ae134dd85f
--- /dev/null
+++ b/settings/DevHome.Settings/Extensions/PageExtensions.cs
@@ -0,0 +1,24 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using DevHome.Common.Services;
+using DevHome.Settings.ViewModels;
+using DevHome.Settings.Views;
+
+namespace DevHome.Settings.Extensions;
+
+public static class PageExtensions
+{
+ public static void ConfigureSettingsPages(this IPageService pageService)
+ {
+ // Settings is not a Tool, so the main page is not configured automatically. Configure it here.
+ pageService.Configure();
+
+ // Configure sub-pages
+ pageService.Configure();
+ pageService.Configure();
+ pageService.Configure();
+ pageService.Configure();
+ pageService.Configure();
+ }
+}
diff --git a/src/Contracts/Services/IPageService.cs b/src/Contracts/Services/IPageService.cs
deleted file mode 100644
index d1725a9e9f..0000000000
--- a/src/Contracts/Services/IPageService.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-namespace DevHome.Contracts.Services;
-
-public interface IPageService
-{
- Type GetPageType(string key);
-}
diff --git a/src/Services/NavigationService.cs b/src/Services/NavigationService.cs
index 90ce9ebf0d..6347b8e9d1 100644
--- a/src/Services/NavigationService.cs
+++ b/src/Services/NavigationService.cs
@@ -3,7 +3,6 @@
using System.Diagnostics.CodeAnalysis;
using DevHome.Common.Services;
-using DevHome.Contracts.Services;
using DevHome.Contracts.ViewModels;
using DevHome.Dashboard.ViewModels;
using DevHome.Helpers;
diff --git a/src/Services/PageService.cs b/src/Services/PageService.cs
index bcdccabf38..dbe3a3e8a4 100644
--- a/src/Services/PageService.cs
+++ b/src/Services/PageService.cs
@@ -5,11 +5,8 @@
using DevHome.Common.Contracts;
using DevHome.Common.Models;
using DevHome.Common.Services;
-using DevHome.Contracts.Services;
-using DevHome.ExtensionLibrary.ViewModels;
-using DevHome.ExtensionLibrary.Views;
-using DevHome.Settings.ViewModels;
-using DevHome.Settings.Views;
+using DevHome.ExtensionLibrary.Extensions;
+using DevHome.Settings.Extensions;
using DevHome.ViewModels;
using DevHome.Views;
using Microsoft.UI.Xaml.Controls;
@@ -30,15 +27,7 @@ public class PageService : IPageService
public PageService(ILocalSettingsService localSettingsService, IExperimentationService experimentationService)
{
- Configure();
- Configure();
- Configure();
- Configure();
- Configure();
- Configure();
- Configure();
- Configure();
-
+ // Configure top-level pages from registered tools
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var group in App.NavConfig.NavMenu.Groups)
{
@@ -52,6 +41,13 @@ where assembly.GetName().Name == tool.Assembly
}
}
+ // Configure other pages
+ Configure();
+
+ this.ConfigureExtensionLibraryPages();
+ this.ConfigureSettingsPages();
+
+ // Configure Experimental Feature pages
ExperimentalFeature.LocalSettingsService = localSettingsService;
foreach (var experimentalFeature in App.NavConfig.ExperimentFeatures ?? Array.Empty())
{
@@ -85,7 +81,7 @@ public Type GetPageType(string key)
return pageType;
}
- private void Configure()
+ public void Configure()
where T_VM : ObservableObject
where T_V : Page
{
diff --git a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs
new file mode 100644
index 0000000000..07131df620
--- /dev/null
+++ b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs
@@ -0,0 +1,16 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using DevHome.Common.Services;
+using DevHome.ExtensionLibrary.ViewModels;
+using DevHome.ExtensionLibrary.Views;
+
+namespace DevHome.ExtensionLibrary.Extensions;
+
+public static class PageExtensions
+{
+ public static void ConfigureExtensionLibraryPages(this IPageService pageService)
+ {
+ pageService.Configure();
+ }
+}
From 57e1a328f02fcd22c15ce6dc777e66f9f023adba Mon Sep 17 00:00:00 2001
From: Jeff Whiteside
Date: Mon, 18 Mar 2024 11:05:30 -0700
Subject: [PATCH 007/121] Quiet Background Processes: Changed toggle to button
(#2411)
* Quiet Background Processes: Changed toggle to button
Minor: Also stopped spamming server each second for clock update.
---
.../Strings/en-us/Resources.resw | 8 ++
.../QuietBackgroundProcessesViewModel.cs | 132 ++++++++++--------
.../Views/QuietBackgroundProcessesPage.xaml | 14 +-
3 files changed, 87 insertions(+), 67 deletions(-)
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw
index bcc14801bd..69698e90ac 100644
--- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw
@@ -62,6 +62,14 @@
Quiet Background Processes
The name of the Quiet Background Processes page
+
+ Start session
+ Button that starts a quiet background session
+
+
+ Stop session
+ Button that stops a quiet background session
+
Silence and track background processes that may hinder device performance
Description of the Quiet Background Processes feature
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs
index 9387a34d2c..bc7eb79b2a 100644
--- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs
@@ -3,6 +3,7 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Helpers;
using DevHome.Common.Services;
using Microsoft.UI.Xaml;
@@ -11,15 +12,24 @@ namespace DevHome.QuietBackgroundProcesses.UI.ViewModels;
public partial class QuietBackgroundProcessesViewModel : ObservableObject
{
- private readonly bool _isFeaturePresent;
- private readonly TimeSpan _zero;
+ private readonly TimeSpan _zero = new TimeSpan(0, 0, 0);
+ private readonly TimeSpan _oneSecond = new TimeSpan(0, 0, 1);
#nullable enable
private DevHome.QuietBackgroundProcesses.QuietBackgroundProcessesSession? _session;
#nullable disable
+ [ObservableProperty]
+ private bool _isFeaturePresent;
+
[ObservableProperty]
private string _sessionStateText;
+ [ObservableProperty]
+ private bool _quietButtonChecked;
+
+ [ObservableProperty]
+ private string _quietButtonText;
+
private DevHome.QuietBackgroundProcesses.QuietBackgroundProcessesSession GetSession()
{
if (_session == null)
@@ -43,72 +53,70 @@ private string GetStatusString(string id)
public QuietBackgroundProcessesViewModel()
{
- _zero = new TimeSpan(0, 0, 0);
+ IsFeaturePresent = DevHome.QuietBackgroundProcesses.QuietBackgroundProcessesSessionManager.IsFeaturePresent();
- _isFeaturePresent = DevHome.QuietBackgroundProcesses.QuietBackgroundProcessesSessionManager.IsFeaturePresent();
- if (!_isFeaturePresent)
+ var running = false;
+ if (IsFeaturePresent)
+ {
+ // Check if an existing quiet session is running.
+ // Note: GetIsActive() won't ever launch a UAC prompt, but GetTimeRemaining() will if no session is running - so be careful with call order
+ running = GetIsActive();
+ }
+ else
{
SessionStateText = GetStatusString("FeatureNotSupported");
- return;
}
// Resume countdown if there's an existing quiet window
- //
- // Note: GetIsActive() won't ever launch a UAC prompt, but GetTimeRemaining() will if no session is running - so be careful with call order
- if (GetIsActive())
- {
- _isToggleOn = true;
- var timeLeftInSeconds = GetTimeRemaining();
- StartCountdownTimer(timeLeftInSeconds);
- }
+ SetQuietSessionRunningState(running);
}
- public bool IsToggleEnabled => _isFeaturePresent;
+ private void SetQuietSessionRunningState(bool running, long? timeLeftInSeconds = null)
+ {
+ if (running)
+ {
+ var seconds = timeLeftInSeconds ?? GetTimeRemaining();
+ StartCountdownTimer(seconds);
+ QuietButtonText = GetString("QuietBackgroundProcesses_QuietButton_Stop");
+ }
+ else
+ {
+ _dispatcherTimer?.Stop();
+ QuietButtonText = GetString("QuietBackgroundProcesses_QuietButton_Start");
+ }
- private bool _isToggleOn;
+ QuietButtonChecked = !running;
+ }
- public bool IsToggleOn
+ [RelayCommand]
+ public void QuietButtonClicked()
{
- get => _isToggleOn;
-
- set
+ if (QuietButtonChecked)
{
- if (_isToggleOn == value)
+ try
{
- return;
+ // Launch the server, which then elevates itself, showing a UAC prompt
+ var timeLeftInSeconds = GetSession().Start();
+ SetQuietSessionRunningState(true, timeLeftInSeconds);
}
-
- _isToggleOn = value;
-
- // Stop any existing timer
- _dispatcherTimer?.Stop();
-
- if (_isToggleOn)
+ catch (Exception ex)
+ {
+ SessionStateText = GetStatusString("SessionError");
+ Log.Logger()?.ReportError("QuietBackgroundProcessesSession::Start failed", ex);
+ }
+ }
+ else
+ {
+ try
{
- try
- {
- // Launch the server, which then elevates itself, showing a UAC prompt
- var timeLeftInSeconds = GetSession().Start();
- StartCountdownTimer(timeLeftInSeconds);
- }
- catch (Exception ex)
- {
- SessionStateText = GetStatusString("SessionError");
- Log.Logger()?.ReportError("QuietBackgroundProcessesSession::Start failed", ex);
- }
+ GetSession().Stop();
+ SetQuietSessionRunningState(false);
+ SessionStateText = GetStatusString("SessionEnded");
}
- else
+ catch (Exception ex)
{
- try
- {
- GetSession().Stop();
- SessionStateText = GetStatusString("SessionEnded");
- }
- catch (Exception ex)
- {
- SessionStateText = GetStatusString("UnableToCancelSession");
- Log.Logger()?.ReportError("QuietBackgroundProcessesSession::Stop failed", ex);
- }
+ SessionStateText = GetStatusString("UnableToCancelSession");
+ Log.Logger()?.ReportError("QuietBackgroundProcessesSession::Stop failed", ex);
}
}
}
@@ -167,29 +175,29 @@ private void StartCountdownTimer(long timeLeftInSeconds)
private void DispatcherTimer_Tick(object sender, object e)
{
- var sessionEnded = false;
+ // Subtract 1 second
+ _secondsLeft = _secondsLeft.Subtract(_oneSecond);
- _secondsLeft = new TimeSpan(0, 0, GetTimeRemaining());
+ // Every 2 minutes ask the server for the actual time remaining (to resolve any drift)
+ if (_secondsLeft.Seconds % 120 == 0)
+ {
+ _secondsLeft = new TimeSpan(0, 0, GetTimeRemaining());
+ }
+ var sessionEnded = false;
if (_secondsLeft.CompareTo(_zero) <= 0)
{
// The window should be closed, but let's confirm with the server
- if (GetSession().IsActive)
- {
- // There has been some drift
- _secondsLeft = new TimeSpan(0, 0, GetTimeRemaining());
- }
- else
+ if (!GetSession().IsActive)
{
- _dispatcherTimer.Stop();
- _secondsLeft = _zero;
- IsToggleOn = false;
sessionEnded = true;
}
}
if (sessionEnded)
{
+ SetQuietSessionRunningState(false);
+ _secondsLeft = _zero;
SessionStateText = GetStatusString("SessionEnded");
}
else
diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml
index ffcdf746b4..e03a58cc51 100644
--- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml
+++ b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesPage.xaml
@@ -16,18 +16,22 @@
-
+
-
-
-
+
+
+
From cf539dc7c4cd2854ba6658cfbe1ce85078e879ab Mon Sep 17 00:00:00 2001
From: Kristen Schau <47155823+krschau@users.noreply.github.com>
Date: Mon, 18 Mar 2024 16:53:41 -0400
Subject: [PATCH 008/121] Make KnownPageKeys available for navigation (#2350)
---
.../DevHome.Settings => common}/Models/Breadcrumb.cs | 2 +-
common/Services/INavigationService.cs | 11 +++++++++++
docs/architecture.md | 2 --
docs/tools.md | 9 +++++++++
.../DevHome.Settings/ViewModels/AboutViewModel.cs | 2 +-
.../DevHome.Settings/ViewModels/AccountsViewModel.cs | 2 +-
.../DevHome.Settings/ViewModels/FeedbackViewModel.cs | 2 +-
.../ViewModels/PreferencesViewModel.cs | 2 +-
.../DevHome.Settings/ViewModels/SettingsViewModel.cs | 1 +
settings/DevHome.Settings/Views/AccountsPage.xaml.cs | 2 +-
.../DevHome.ExtensionLibrary.csproj | 1 -
.../ViewModels/ExtensionLibraryViewModel.cs | 3 +--
.../ViewModels/ExtensionSettingsViewModel.cs | 2 +-
.../DevHome.SetupFlow/DevHome.SetupFlow.csproj | 2 --
.../DevHome.SetupFlow/ViewModels/SummaryViewModel.cs | 6 ++----
15 files changed, 31 insertions(+), 18 deletions(-)
rename {settings/DevHome.Settings => common}/Models/Breadcrumb.cs (90%)
diff --git a/settings/DevHome.Settings/Models/Breadcrumb.cs b/common/Models/Breadcrumb.cs
similarity index 90%
rename from settings/DevHome.Settings/Models/Breadcrumb.cs
rename to common/Models/Breadcrumb.cs
index 2662c50a77..4a9c50adce 100644
--- a/settings/DevHome.Settings/Models/Breadcrumb.cs
+++ b/common/Models/Breadcrumb.cs
@@ -5,7 +5,7 @@
using DevHome.Common.Services;
using Microsoft.UI.Xaml;
-namespace DevHome.Settings.Models;
+namespace DevHome.Common.Models;
public class Breadcrumb
{
diff --git a/common/Services/INavigationService.cs b/common/Services/INavigationService.cs
index f7e87e8756..0a592fc9a9 100644
--- a/common/Services/INavigationService.cs
+++ b/common/Services/INavigationService.cs
@@ -37,3 +37,14 @@ string DefaultPage
bool GoForward();
}
+
+// Expose known page keys so that a project doesn't need to include a ProjectReference to another project
+// just to navigate to another page.
+public static class KnownPageKeys
+{
+ public static readonly string Dashboard = "DevHome.Dashboard.ViewModels.DashboardViewModel";
+ public static readonly string Extensions = "DevHome.ExtensionLibrary.ViewModels.ExtensionLibraryViewModel";
+ public static readonly string WhatsNew = "DevHome.ViewModels.WhatsNewViewModel";
+ public static readonly string Settings = "DevHome.Settings.ViewModels.SettingsViewModel";
+ public static readonly string Feedback = "DevHome.Settings.ViewModels.FeedbackViewModel";
+}
diff --git a/docs/architecture.md b/docs/architecture.md
index 47612e7aef..fa3a4126e0 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -28,8 +28,6 @@ graph TD;
DevHome.SetupFlow.Common-->DevHome.SetupFlow.ElevatedServer;
DevHome.SetupFlow.ElevatedComponent-->DevHome.SetupFlow.ElevatedServer;
DevHome.SetupFlow.ElevatedComponent.Projection-->DevHome.SetupFlow;
- DevHome.Dashboard-->DevHome.SetupFlow;
- DevHome.Settings-->DevHome.SetupFlow;
CoreWidgetProvider-->DevHome;
DevHome.Dashboard-->DevHome;
DevHome.Experiments-->DevHome;
diff --git a/docs/tools.md b/docs/tools.md
index 4768b49eed..5a76119de2 100644
--- a/docs/tools.md
+++ b/docs/tools.md
@@ -65,6 +65,15 @@ In order to allow navigation to your tool, your page and ViewModel must be regis
In order to do so, you must create an extension method for the PageService inside your tool. See examples in [Settings](../settings/DevHome.Settings/Extensions/PageExtensions.cs) or [Extensions](../tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs). Then, call your extension from the [PageService](../src/Services/PageService.cs).
+#### Navigating away from your tool
+
+If you want a user action (such as clicking a link) to navigate away from your tool and your project does not otherwise rely on the destination project, do not create a PackageReference to the destination project from yours. Instead, add the destination page to `INavigationService.KnownPageKeys` and use it for navigation, like in this example:
+```cs
+navigationService.NavigateTo(KnownPageKeys.);
+```
+
+This keeps the dependency tree simple, and prevents circular references when two projects want to navigate to each other.
+
## Existing tools
[Dashboard](./tools/Dashboard.md)
diff --git a/settings/DevHome.Settings/ViewModels/AboutViewModel.cs b/settings/DevHome.Settings/ViewModels/AboutViewModel.cs
index 352d306876..4d482042c7 100644
--- a/settings/DevHome.Settings/ViewModels/AboutViewModel.cs
+++ b/settings/DevHome.Settings/ViewModels/AboutViewModel.cs
@@ -5,8 +5,8 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Extensions;
+using DevHome.Common.Models;
using DevHome.Common.Services;
-using DevHome.Settings.Models;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
diff --git a/settings/DevHome.Settings/ViewModels/AccountsViewModel.cs b/settings/DevHome.Settings/ViewModels/AccountsViewModel.cs
index a68d3e4b2a..b79a0a396a 100644
--- a/settings/DevHome.Settings/ViewModels/AccountsViewModel.cs
+++ b/settings/DevHome.Settings/ViewModels/AccountsViewModel.cs
@@ -8,8 +8,8 @@
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Contracts.Services;
using DevHome.Common.Extensions;
+using DevHome.Common.Models;
using DevHome.Common.Services;
-using DevHome.Settings.Models;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
diff --git a/settings/DevHome.Settings/ViewModels/FeedbackViewModel.cs b/settings/DevHome.Settings/ViewModels/FeedbackViewModel.cs
index 9609dbc2f7..ffcd31b38e 100644
--- a/settings/DevHome.Settings/ViewModels/FeedbackViewModel.cs
+++ b/settings/DevHome.Settings/ViewModels/FeedbackViewModel.cs
@@ -6,9 +6,9 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Extensions;
+using DevHome.Common.Models;
using DevHome.Common.Services;
using DevHome.Contracts.Services;
-using DevHome.Settings.Models;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
diff --git a/settings/DevHome.Settings/ViewModels/PreferencesViewModel.cs b/settings/DevHome.Settings/ViewModels/PreferencesViewModel.cs
index 0d71a9399d..49ec130ada 100644
--- a/settings/DevHome.Settings/ViewModels/PreferencesViewModel.cs
+++ b/settings/DevHome.Settings/ViewModels/PreferencesViewModel.cs
@@ -5,9 +5,9 @@
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
+using DevHome.Common.Models;
using DevHome.Common.Services;
using DevHome.Contracts.Services;
-using DevHome.Settings.Models;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
diff --git a/settings/DevHome.Settings/ViewModels/SettingsViewModel.cs b/settings/DevHome.Settings/ViewModels/SettingsViewModel.cs
index 5fdbd839c1..79661087ee 100644
--- a/settings/DevHome.Settings/ViewModels/SettingsViewModel.cs
+++ b/settings/DevHome.Settings/ViewModels/SettingsViewModel.cs
@@ -5,6 +5,7 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Extensions;
+using DevHome.Common.Models;
using DevHome.Common.Services;
using DevHome.Settings.Models;
using Microsoft.UI.Xaml;
diff --git a/settings/DevHome.Settings/Views/AccountsPage.xaml.cs b/settings/DevHome.Settings/Views/AccountsPage.xaml.cs
index 09a4e8cfec..40a51c18f5 100644
--- a/settings/DevHome.Settings/Views/AccountsPage.xaml.cs
+++ b/settings/DevHome.Settings/Views/AccountsPage.xaml.cs
@@ -66,7 +66,7 @@ private async void AddAccountButton_Click(object sender, RoutedEventArgs e)
private void FindExtensions()
{
var navigationService = Application.Current.GetService();
- navigationService.NavigateTo("DevHome.ExtensionLibrary.ViewModels.ExtensionLibraryViewModel");
+ navigationService.NavigateTo(KnownPageKeys.Extensions);
}
private async void AddDeveloperId_Click(object sender, RoutedEventArgs e)
diff --git a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/DevHome.ExtensionLibrary.csproj b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/DevHome.ExtensionLibrary.csproj
index ace6f4a2dd..3e4bc667bb 100644
--- a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/DevHome.ExtensionLibrary.csproj
+++ b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/DevHome.ExtensionLibrary.csproj
@@ -19,7 +19,6 @@
-
diff --git a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/ExtensionLibraryViewModel.cs b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/ExtensionLibraryViewModel.cs
index 2f9710adab..215b0c189e 100644
--- a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/ExtensionLibraryViewModel.cs
+++ b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/ExtensionLibraryViewModel.cs
@@ -12,7 +12,6 @@
using DevHome.Common.Extensions;
using DevHome.Common.Services;
using DevHome.ExtensionLibrary.Helpers;
-using DevHome.Settings.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.Windows.DevHome.SDK;
using Windows.ApplicationModel;
@@ -208,6 +207,6 @@ public Visibility GetNoAvailablePackagesVisibility(int availablePackagesCount, b
public void SendFeedbackClick()
{
var navigationService = Application.Current.GetService();
- _ = navigationService.NavigateTo(typeof(FeedbackViewModel).FullName!);
+ _ = navigationService.NavigateTo(KnownPageKeys.Feedback);
}
}
diff --git a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/ExtensionSettingsViewModel.cs b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/ExtensionSettingsViewModel.cs
index 98064f92ea..94d7258199 100644
--- a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/ExtensionSettingsViewModel.cs
+++ b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/ExtensionSettingsViewModel.cs
@@ -6,10 +6,10 @@
using AdaptiveCards.Rendering.WinUI3;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
+using DevHome.Common.Models;
using DevHome.Common.Services;
using DevHome.Common.Views;
using DevHome.Logging;
-using DevHome.Settings.Models;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.DevHome.SDK;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj b/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj
index a94b1854ac..13d2bf5221 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj
+++ b/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj
@@ -26,8 +26,6 @@
-
-
Projection
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs
index 219a3f0890..7e3e7156b3 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SummaryViewModel.cs
@@ -13,8 +13,6 @@
using DevHome.Common.Services;
using DevHome.Common.TelemetryEvents.SetupFlow;
using DevHome.Contracts.Services;
-using DevHome.Dashboard.ViewModels;
-using DevHome.Settings.ViewModels;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.Services;
@@ -151,7 +149,7 @@ public void GoToMainPage()
public void GoToDashboard()
{
TelemetryFactory.Get().Log("Summary_NavigateTo_Event", LogLevel.Critical, new NavigateFromSummaryEvent("Dashboard"), Orchestrator.ActivityId);
- _host.GetService().NavigateTo(typeof(DashboardViewModel).FullName);
+ _host.GetService().NavigateTo(KnownPageKeys.Dashboard);
_setupFlowViewModel.TerminateCurrentFlow("Summary_GoToDashboard");
}
@@ -159,7 +157,7 @@ public void GoToDashboard()
public void GoToDevHomeSettings()
{
TelemetryFactory.Get().Log("Summary_NavigateTo_Event", LogLevel.Critical, new NavigateFromSummaryEvent("DevHomeSettings"), Orchestrator.ActivityId);
- _host.GetService().NavigateTo(typeof(SettingsViewModel).FullName);
+ _host.GetService().NavigateTo(KnownPageKeys.Settings);
_setupFlowViewModel.TerminateCurrentFlow("Summary_GoToSettings");
}
From 9c74073dc7f44371c083647506064238940b6dd1 Mon Sep 17 00:00:00 2001
From: Darren Hoehna
Date: Tue, 19 Mar 2024 13:42:41 -0700
Subject: [PATCH 009/121] Adding IRepositoryProvider2 (#2430)
* IDL
* Updating Build version
---------
Co-authored-by: Darren Hoehna
---
build/azure-pipelines.yml | 2 +-
.../Microsoft.Windows.DevHome.SDK.idl | 57 +++++++++++++++++-
.../Microsoft.Windows.DevHome.SDK.vcxproj | 2 +
.../RepositoriesResult.cpp | 1 +
.../RepositoriesSearchResult.cpp | 58 +++++++++++++++++++
.../RepositoriesSearchResult.h | 32 ++++++++++
6 files changed, 150 insertions(+), 2 deletions(-)
create mode 100644 extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesSearchResult.cpp
create mode 100644 extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesSearchResult.h
diff --git a/build/azure-pipelines.yml b/build/azure-pipelines.yml
index 76bd2ac4c3..1cead03cab 100644
--- a/build/azure-pipelines.yml
+++ b/build/azure-pipelines.yml
@@ -22,7 +22,7 @@ parameters:
variables:
# MSIXVersion's second part should always be odd to account for stub app's version
MSIXVersion: '0.1201'
- VersionOfSDK: '0.200'
+ VersionOfSDK: '0.300'
solution: '**/DevHome.sln'
appxPackageDir: 'AppxPackages'
testOutputArtifactDir: 'TestResults'
diff --git a/extensionsdk/Microsoft.Windows.DevHome.SDK/Microsoft.Windows.DevHome.SDK.idl b/extensionsdk/Microsoft.Windows.DevHome.SDK/Microsoft.Windows.DevHome.SDK.idl
index e7b6b40ec8..7115dc1a66 100644
--- a/extensionsdk/Microsoft.Windows.DevHome.SDK/Microsoft.Windows.DevHome.SDK.idl
+++ b/extensionsdk/Microsoft.Windows.DevHome.SDK/Microsoft.Windows.DevHome.SDK.idl
@@ -1,6 +1,6 @@
namespace Microsoft.Windows.DevHome.SDK
{
- [contractversion(2)]
+ [contractversion(3)]
apicontract DevHomeContract {}
[contract(Microsoft.Windows.DevHome.SDK.DevHomeContract, 1)]
@@ -77,6 +77,30 @@ namespace Microsoft.Windows.DevHome.SDK
Windows.Foundation.IAsyncOperation CloneRepositoryAsync(IRepository repository, String cloneDestination, IDeveloperId developerId);
};
+ [contract(Microsoft.Windows.DevHome.SDK.DevHomeContract, 3)] interface IRepositoryProvider2
+ requires IRepositoryProvider
+ {
+ String[] SearchFieldNames
+ {
+ get;
+ };
+
+ Boolean IsSearchingSupported
+ {
+ get;
+ };
+
+ String AskToSearchLabel
+ {
+ get;
+ };
+
+ // This should return a list of suggestions given fieldValues.
+ // "Suggestions" is dependant on the extension and how it keeps track of repositories.
+ Windows.Foundation.IAsyncOperation > GetValuesForSearchFieldAsync(IMapView fieldValues, String requestedSearchField, IDeveloperId developerId);
+ Windows.Foundation.IAsyncOperation GetRepositoriesAsync(IMapView fieldValues, IDeveloperId developerId);
+ };
+
[contract(Microsoft.Windows.DevHome.SDK.DevHomeContract, 1)]
runtimeclass RepositoryResult {
RepositoryResult(IRepository repository);
@@ -107,6 +131,37 @@ namespace Microsoft.Windows.DevHome.SDK
};
};
+ [contract(Microsoft.Windows.DevHome.SDK.DevHomeContract, 3)] runtimeclass RepositoriesSearchResult {
+ RepositoriesSearchResult(IIterable repositories);
+ RepositoriesSearchResult(IIterable repositories, String selectionsOptionsLabel, String[] selectionOptions, String selectionOptionsName);
+ RepositoriesSearchResult(HRESULT e, String diagnosticText);
+
+ IIterable Repositories
+ {
+ get;
+ };
+
+ String SelectionOptionsLabel
+ {
+ get;
+ };
+
+ String[] SelectionOptions
+ {
+ get;
+ };
+
+ String SelectionOptionsName
+ {
+ get;
+ };
+
+ ProviderOperationResult Result
+ {
+ get;
+ };
+ };
+
[contract(Microsoft.Windows.DevHome.SDK.DevHomeContract, 1)]
runtimeclass RepositoryUriSupportResult {
RepositoryUriSupportResult(Boolean isSupported);
diff --git a/extensionsdk/Microsoft.Windows.DevHome.SDK/Microsoft.Windows.DevHome.SDK.vcxproj b/extensionsdk/Microsoft.Windows.DevHome.SDK/Microsoft.Windows.DevHome.SDK.vcxproj
index 315475c8fe..dabcd9af2e 100644
--- a/extensionsdk/Microsoft.Windows.DevHome.SDK/Microsoft.Windows.DevHome.SDK.vcxproj
+++ b/extensionsdk/Microsoft.Windows.DevHome.SDK/Microsoft.Windows.DevHome.SDK.vcxproj
@@ -226,6 +226,7 @@
+
@@ -260,6 +261,7 @@
+
diff --git a/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesResult.cpp b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesResult.cpp
index 775d63a36c..309282d0f3 100644
--- a/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesResult.cpp
+++ b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesResult.cpp
@@ -13,6 +13,7 @@ namespace winrt::Microsoft::Windows::DevHome::SDK::implementation
RepositoriesResult::RepositoriesResult(winrt::hresult const& e, hstring const& diagnosticText)
{
_Result = std::make_shared(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Failure, winrt::hresult(e), winrt::to_hstring("Something went wrong"), diagnosticText);
+ _Result = std::make_shared(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Failure, winrt::hresult(e), diagnosticText, diagnosticText);
}
winrt::Windows::Foundation::Collections::IIterable RepositoriesResult::Repositories()
diff --git a/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesSearchResult.cpp b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesSearchResult.cpp
new file mode 100644
index 0000000000..985141e4f0
--- /dev/null
+++ b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesSearchResult.cpp
@@ -0,0 +1,58 @@
+#include "pch.h"
+#include "RepositoriesSearchResult.h"
+#include "RepositoriesSearchResult.g.cpp"
+
+namespace winrt::Microsoft::Windows::DevHome::SDK::implementation
+{
+ RepositoriesSearchResult::RepositoriesSearchResult(winrt::Windows::Foundation::Collections::IIterable const& repositories) :
+ _Repositories(std::make_shared>(repositories)),
+ _SelectionOptionsLabel(L""),
+ _SelectionOptionsName(L""),
+ _SelectionOptions(std::vector()),
+ _Result(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationResult(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Success, winrt::hresult(S_OK), winrt::to_hstring(""), winrt::to_hstring("")))
+ {
+ }
+
+ RepositoriesSearchResult::RepositoriesSearchResult(winrt::Windows::Foundation::Collections::IIterable const& repositories, hstring const& selectionOptionsLabel, array_view selectionOptions, hstring const& selectionOptionsName) :
+ _Repositories(std::make_shared>(repositories)),
+ _SelectionOptionsLabel(selectionOptionsLabel),
+ _SelectionOptionsName(selectionOptionsName),
+ _SelectionOptions(std::vector{ selectionOptions.begin(), selectionOptions.end() }),
+ _Result(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationResult(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Success, winrt::hresult(S_OK), winrt::to_hstring(""), winrt::to_hstring("")))
+ {
+ }
+
+ RepositoriesSearchResult::RepositoriesSearchResult(winrt::hresult const& e, hstring const& diagnosticText) :
+ _Repositories(std::make_shared>(winrt::Windows::Foundation::Collections::IIterable())),
+ _SelectionOptionsLabel(L""),
+ _SelectionOptionsName(L""),
+ _SelectionOptions(std::vector()),
+ _Result(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationResult(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Failure, winrt::hresult(e), diagnosticText, diagnosticText))
+ {
+ }
+
+ winrt::Windows::Foundation::Collections::IIterable RepositoriesSearchResult::Repositories()
+ {
+ return *_Repositories.get();
+ }
+
+ hstring RepositoriesSearchResult::SelectionOptionsLabel()
+ {
+ return _SelectionOptionsLabel;
+ }
+
+ com_array RepositoriesSearchResult::SelectionOptions()
+ {
+ return winrt::com_array{ _SelectionOptions };
+ }
+
+ hstring RepositoriesSearchResult::SelectionOptionsName()
+ {
+ return _SelectionOptionsName;
+ }
+
+ winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationResult RepositoriesSearchResult::Result()
+ {
+ return _Result;
+ }
+}
\ No newline at end of file
diff --git a/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesSearchResult.h b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesSearchResult.h
new file mode 100644
index 0000000000..2a7c864dae
--- /dev/null
+++ b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoriesSearchResult.h
@@ -0,0 +1,32 @@
+#pragma once
+#include "RepositoriesSearchResult.g.h"
+
+namespace winrt::Microsoft::Windows::DevHome::SDK::implementation
+{
+ struct RepositoriesSearchResult : RepositoriesSearchResultT
+ {
+ RepositoriesSearchResult() = default;
+
+ RepositoriesSearchResult(winrt::Windows::Foundation::Collections::IIterable const& repositories);
+ RepositoriesSearchResult(winrt::Windows::Foundation::Collections::IIterable const& repositories, hstring const& searchPath, array_view selectionOptions, hstring const& selectionOptionsName);
+ RepositoriesSearchResult(winrt::hresult const& e, hstring const& diagnosticText);
+ winrt::Windows::Foundation::Collections::IIterable Repositories();
+ hstring SelectionOptionsLabel();
+ com_array SelectionOptions();
+ hstring SelectionOptionsName();
+ winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationResult Result();
+
+ private:
+ winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationResult _Result;
+ std::shared_ptr> _Repositories;
+ hstring _SelectionOptionsLabel;
+ std::vector _SelectionOptions;
+ hstring _SelectionOptionsName;
+ };
+}
+namespace winrt::Microsoft::Windows::DevHome::SDK::factory_implementation
+{
+ struct RepositoriesSearchResult : RepositoriesSearchResultT
+ {
+ };
+}
\ No newline at end of file
From f3b2bbfed01c3673d6bfb8a8aabb1c4adce8c0f6 Mon Sep 17 00:00:00 2001
From: sshilov7 <51001703+sshilov7@users.noreply.github.com>
Date: Tue, 19 Mar 2024 14:28:42 -0700
Subject: [PATCH 010/121] Add DevSetupEngine COM permissions and Dispose method
to force shutdown. (#2358)
---
.../src/DevSetupAgent/Requests/ConfigureRequest.cs | 9 +++++++--
HyperVExtension/src/DevSetupEngine/Program.cs | 14 +++++++++++++-
.../Microsoft.Windows.DevHome.DevSetupEngine.idl | 1 +
3 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/ConfigureRequest.cs b/HyperVExtension/src/DevSetupAgent/Requests/ConfigureRequest.cs
index 8f8b699055..57f27437a4 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/ConfigureRequest.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/ConfigureRequest.cs
@@ -32,8 +32,8 @@ public ConfigureRequest(IRequestContext requestContext)
public override IHostResponse Execute(ProgressHandler progressHandler, CancellationToken stoppingToken)
{
- // DevSetupEngine needs to be started manually from command line in the test.
var devSetupEnginePtr = IntPtr.Zero;
+ var devSetupEngine = default(IDevSetupEngine);
try
{
var hr = PInvoke.CoCreateInstance(Guid.Parse("82E86C64-A8B9-44F9-9323-C37982F2D8BE"), null, CLSCTX.CLSCTX_LOCAL_SERVER, typeof(IDevSetupEngine).GUID, out var devSetupEngineObj);
@@ -44,7 +44,7 @@ public override IHostResponse Execute(ProgressHandler progressHandler, Cancellat
devSetupEnginePtr = Marshal.GetIUnknownForObject(devSetupEngineObj);
- var devSetupEngine = MarshalInterface.FromAbi(devSetupEnginePtr);
+ devSetupEngine = MarshalInterface.FromAbi(devSetupEnginePtr);
var operation = devSetupEngine.ApplyConfigurationAsync(ConfigureData);
uint progressCounter = 0;
@@ -66,6 +66,11 @@ public override IHostResponse Execute(ProgressHandler progressHandler, Cancellat
{
Marshal.Release(devSetupEnginePtr);
}
+
+ if (devSetupEngine != null)
+ {
+ devSetupEngine.Dispose();
+ }
}
}
}
diff --git a/HyperVExtension/src/DevSetupEngine/Program.cs b/HyperVExtension/src/DevSetupEngine/Program.cs
index 44816e9348..1b1bd2ac4b 100644
--- a/HyperVExtension/src/DevSetupEngine/Program.cs
+++ b/HyperVExtension/src/DevSetupEngine/Program.cs
@@ -2,7 +2,7 @@
// Licensed under the MIT License.
using System.ComponentModel;
-using HyperVExtension.DevSetupEngine;
+using System.Security.AccessControl;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Win32;
@@ -81,6 +81,18 @@ private static void RegisterComServer()
var appIdKey = Registry.LocalMachine.CreateSubKey(AppIdPath + appId, true) ?? throw new Win32Exception();
appIdKey.SetValue("RunAs", "Interactive User", RegistryValueKind.String);
+ // O:PSG: BU Owner: principal self, Group: Built-in users
+ // (A; ; 0xB; ; ; SY) Allow SYSTEM
+ // (A; ; 0xB; ; ; LS) Allow Local Service
+ // (A; ; 0xB; ; ; PS) Allow Principal self
+ // 0xB = (COM_RIGHTS_EXECUTE | COM_RIGHTS_EXECUTE_LOCAL | COM_RIGHTS_ACTIVATE_LOCAL
+ var permissions = "O:PSG:BUD:(A;;0xB;;;SY)(A;;0xB;;;LS)(A;;0xB;;;PS)";
+ RawSecurityDescriptor rawSd = new RawSecurityDescriptor(permissions);
+ var sdBinaryForm = new byte[rawSd.BinaryLength];
+ rawSd.GetBinaryForm(sdBinaryForm, 0);
+ appIdKey.SetValue("AccessPermission", sdBinaryForm, RegistryValueKind.Binary);
+ appIdKey.SetValue("LaunchPermission", sdBinaryForm, RegistryValueKind.Binary);
+
var clsIdKey = Registry.LocalMachine.CreateSubKey(ClsIdIdPath + appId, true) ?? throw new Win32Exception();
clsIdKey.SetValue("AppID", appId);
diff --git a/HyperVExtension/src/DevSetupEngineIdl/Microsoft.Windows.DevHome.DevSetupEngine.idl b/HyperVExtension/src/DevSetupEngineIdl/Microsoft.Windows.DevHome.DevSetupEngine.idl
index a2dc1707b7..de0ea82f9a 100644
--- a/HyperVExtension/src/DevSetupEngineIdl/Microsoft.Windows.DevHome.DevSetupEngine.idl
+++ b/HyperVExtension/src/DevSetupEngineIdl/Microsoft.Windows.DevHome.DevSetupEngine.idl
@@ -217,5 +217,6 @@ namespace Microsoft.Windows.DevHome.DevSetupEngine
{
// Applies the configuration set state.
Windows.Foundation.IAsyncOperationWithProgress ApplyConfigurationAsync(String content);
+ void Dispose();
};
}
\ No newline at end of file
From 4c7381c6b48cca55ecc70a2f1c1502dff560c8d9 Mon Sep 17 00:00:00 2001
From: Gobinath B
Date: Wed, 20 Mar 2024 03:21:34 +0530
Subject: [PATCH 011/121] Add Usage Percentage to Memory widget (#2335)
---
.../Templates/SystemMemoryTemplate.json | 327 ++++++++++--------
1 file changed, 175 insertions(+), 152 deletions(-)
diff --git a/extensions/CoreWidgetProvider/Widgets/Templates/SystemMemoryTemplate.json b/extensions/CoreWidgetProvider/Widgets/Templates/SystemMemoryTemplate.json
index 8ae5b289b9..eaf2ce046c 100644
--- a/extensions/CoreWidgetProvider/Widgets/Templates/SystemMemoryTemplate.json
+++ b/extensions/CoreWidgetProvider/Widgets/Templates/SystemMemoryTemplate.json
@@ -1,152 +1,175 @@
-{
- "type": "AdaptiveCard",
- "body": [
- {
- "type": "Container",
- "$when": "${errorMessage != null}",
- "items": [
- {
- "type": "TextBlock",
- "text": "${errorMessage}",
- "wrap": true,
- "size": "small"
- }
- ],
- "style": "warning"
- },
- {
- "type": "Container",
- "$when": "${errorMessage == null}",
- "items": [
- {
- "type": "Image",
- "url": "${memGraphUrl}",
- "height": "${chartHeight}",
- "width": "${chartWidth}",
- "horizontalAlignment": "center"
- },
- {
- "type": "ColumnSet",
- "columns": [
- {
- "type": "Column",
- "items": [
- {
- "text": "%Memory_Widget_Template/UsedMemory%",
- "type": "TextBlock",
- "size": "small",
- "isSubtle": true
- },
- {
- "text": "${usedMem}",
- "type": "TextBlock",
- "size": "large",
- "weight": "bolder"
- }
- ]
- },
- {
- "type": "Column",
- "items": [
- {
- "text": "%Memory_Widget_Template/AllMemory%",
- "type": "TextBlock",
- "size": "small",
- "isSubtle": true,
- "horizontalAlignment": "right"
- },
- {
- "text": "${allMem}",
- "type": "TextBlock",
- "size": "large",
- "weight": "bolder",
- "horizontalAlignment": "right"
- }
- ]
- }
- ]
- },
- {
- "type": "ColumnSet",
- "columns": [
- {
- "type": "Column",
- "items": [
- {
- "text": "%Memory_Widget_Template/Committed%",
- "type": "TextBlock",
- "size": "small",
- "isSubtle": true
- },
- {
- "text": "${committedMem}/${committedLimitMem}",
- "type": "TextBlock",
- "size": "medium"
- }
- ]
- },
- {
- "type": "Column",
- "items": [
- {
- "text": "%Memory_Widget_Template/Cached%",
- "type": "TextBlock",
- "size": "small",
- "isSubtle": true,
- "horizontalAlignment": "right"
- },
- {
- "text": "${cachedMem}",
- "type": "TextBlock",
- "size": "medium",
- "horizontalAlignment": "right"
- }
- ]
- }
- ]
- },
- {
- "type": "ColumnSet",
- "columns": [
- {
- "type": "Column",
- "items": [
- {
- "text": "%Memory_Widget_Template/PagedPool%",
- "type": "TextBlock",
- "size": "small",
- "isSubtle": true
- },
- {
- "text": "${pagedPoolMem}",
- "type": "TextBlock",
- "size": "medium"
- }
- ]
- },
- {
- "type": "Column",
- "items": [
- {
- "text": "%Memory_Widget_Template/NonPagedPool%",
- "type": "TextBlock",
- "size": "small",
- "isSubtle": true,
- "horizontalAlignment": "right"
- },
- {
- "text": "${nonPagedPoolMem}",
- "type": "TextBlock",
- "size": "medium",
- "horizontalAlignment": "right"
- }
- ]
- }
- ]
- }
- ]
- }
- ],
- "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
- "version": "1.5"
-}
\ No newline at end of file
+{
+ "type": "AdaptiveCard",
+ "body": [
+ {
+ "type": "Container",
+ "$when": "${errorMessage != null}",
+ "items": [
+ {
+ "type": "TextBlock",
+ "text": "${errorMessage}",
+ "wrap": true,
+ "size": "small"
+ }
+ ],
+ "style": "warning"
+ },
+ {
+ "type": "Container",
+ "$when": "${errorMessage == null}",
+ "items": [
+ {
+ "type": "Image",
+ "url": "${memGraphUrl}",
+ "height": "${chartHeight}",
+ "width": "${chartWidth}",
+ "horizontalAlignment": "center"
+ },
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%Memory_Widget_Template/UsedMemory%",
+ "type": "TextBlock",
+ "size": "small",
+ "isSubtle": true
+ },
+ {
+ "text": "${usedMem}",
+ "type": "TextBlock",
+ "size": "large",
+ "weight": "bolder"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%Memory_Widget_Template/AllMemory%",
+ "type": "TextBlock",
+ "size": "small",
+ "isSubtle": true,
+ "horizontalAlignment": "right"
+ },
+ {
+ "text": "${allMem}",
+ "type": "TextBlock",
+ "size": "large",
+ "weight": "bolder",
+ "horizontalAlignment": "right"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%Memory_Widget_Template/Committed%",
+ "type": "TextBlock",
+ "size": "small",
+ "isSubtle": true
+ },
+ {
+ "text": "${committedMem}/${committedLimitMem}",
+ "type": "TextBlock",
+ "size": "medium"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%Memory_Widget_Template/Cached%",
+ "type": "TextBlock",
+ "size": "small",
+ "isSubtle": true,
+ "horizontalAlignment": "right"
+ },
+ {
+ "text": "${cachedMem}",
+ "type": "TextBlock",
+ "size": "medium",
+ "horizontalAlignment": "right"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%Memory_Widget_Template/PagedPool%",
+ "type": "TextBlock",
+ "size": "small",
+ "isSubtle": true
+ },
+ {
+ "text": "${pagedPoolMem}",
+ "type": "TextBlock",
+ "size": "medium"
+ }
+ ]
+ },
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%Memory_Widget_Template/NonPagedPool%",
+ "type": "TextBlock",
+ "size": "small",
+ "isSubtle": true,
+ "horizontalAlignment": "right"
+ },
+ {
+ "text": "${nonPagedPoolMem}",
+ "type": "TextBlock",
+ "size": "medium",
+ "horizontalAlignment": "right"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "ColumnSet",
+ "columns": [
+ {
+ "type": "Column",
+ "items": [
+ {
+ "text": "%Memory_Widget_Template/MemoryUsage%",
+ "type": "TextBlock",
+ "size": "small",
+ "isSubtle": true,
+ "horizontalAlignment": "right"
+ },
+ {
+ "text": "${memUsage}",
+ "type": "TextBlock",
+ "size": "medium",
+ "horizontalAlignment": "right"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
+ "version": "1.5"
+}
From 42c54a044fd3c89c7732ff66a0123ae56c39984d Mon Sep 17 00:00:00 2001
From: Kristen Schau <47155823+krschau@users.noreply.github.com>
Date: Tue, 19 Mar 2024 17:54:02 -0400
Subject: [PATCH 012/121] Fix scroll regions across Dev Home (#2423)
---
.../Styles/HorizontalCardStyles.xaml | 7 +-
.../Templates/EnvironmentsTemplates.xaml | 1 -
.../DevHome.Settings/Views/AboutPage.xaml | 11 +-
.../DevHome.Settings/Views/AccountsPage.xaml | 10 +-
.../Views/ExperimentalFeaturesPage.xaml | 10 +-
.../DevHome.Settings/Views/FeedbackPage.xaml | 12 +-
.../Views/PreferencesPage.xaml | 18 +-
.../DevHome.Settings/Views/SettingsPage.xaml | 10 +-
src/Styles/Thickness.xaml | 2 +
src/Views/WhatsNewPage.xaml | 11 +-
.../Views/DashboardView.xaml | 9 +-
.../Views/LandingPage.xaml | 56 +-
.../Views/ExtensionLibraryView.xaml | 4 +-
.../Views/ExtensionSettingsPage.xaml | 9 +-
.../Controls/SetupShell.xaml | 20 +-
.../Controls/SetupShell.xaml.cs | 2 -
.../Views/AppManagementView.xaml | 2 +-
.../DevHome.SetupFlow/Views/LoadingView.xaml | 2 +-
.../DevHome.SetupFlow/Views/MainPageView.xaml | 4 +-
.../Views/RepoConfigView.xaml | 2 +-
.../Views/SetupFlowPage.xaml | 9 +-
.../Views/SetupTargetView.xaml | 4 +-
.../DevHome.SetupFlow/Views/SummaryView.xaml | 650 +++++++++---------
23 files changed, 432 insertions(+), 433 deletions(-)
diff --git a/common/Environments/Styles/HorizontalCardStyles.xaml b/common/Environments/Styles/HorizontalCardStyles.xaml
index 7b9123729e..a6b2e98f49 100644
--- a/common/Environments/Styles/HorizontalCardStyles.xaml
+++ b/common/Environments/Styles/HorizontalCardStyles.xaml
@@ -15,6 +15,7 @@
+
@@ -33,7 +34,6 @@
BasedOn="{StaticResource DefaultListViewItemStyle}">
-
@@ -42,7 +42,9 @@
x:Key="HorizontalCardListViewItemContainerForManagementPageStyle"
TargetType="ListViewItem"
BasedOn="{StaticResource DefaultListViewItemStyle}">
-
+
+
+
@@ -50,7 +52,6 @@
diff --git a/common/Environments/Templates/EnvironmentsTemplates.xaml b/common/Environments/Templates/EnvironmentsTemplates.xaml
index 4538248f20..ccbc834b19 100644
--- a/common/Environments/Templates/EnvironmentsTemplates.xaml
+++ b/common/Environments/Templates/EnvironmentsTemplates.xaml
@@ -4,7 +4,6 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
- xmlns:models="using:DevHome.Common.Environments.Models"
xmlns:converters="using:CommunityToolkit.WinUI.Converters">
+ 40,0,40,22
36,24,36,0
diff --git a/src/Views/WhatsNewPage.xaml b/src/Views/WhatsNewPage.xaml
index 19da4938a4..256df8de94 100644
--- a/src/Views/WhatsNewPage.xaml
+++ b/src/Views/WhatsNewPage.xaml
@@ -9,7 +9,6 @@
xmlns:models="using:DevHome.Models"
xmlns:behaviors="using:DevHome.Common.Behaviors"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
- xmlns:converters="using:CommunityToolkit.WinUI.Converters"
behaviors:NavigationViewHeaderBehavior.HeaderMode="Never"
Loaded="OnLoaded"
SizeChanged="OnSizeChanged"
@@ -34,10 +33,14 @@
-
-
+
+
-
+
diff --git a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml
index 0c02bf3f56..22512232aa 100644
--- a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml
+++ b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml
@@ -44,16 +44,17 @@
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Controls/SetupShell.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Controls/SetupShell.xaml.cs
index 59efa6b50a..6a5cc42e19 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Controls/SetupShell.xaml.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Controls/SetupShell.xaml.cs
@@ -1,11 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using DevHome.SetupFlow.Services;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Markup;
namespace DevHome.SetupFlow.Controls;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/AppManagementView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/AppManagementView.xaml
index c302b0051f..a87cb0358b 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/AppManagementView.xaml
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/AppManagementView.xaml
@@ -31,7 +31,7 @@
-
+
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/LoadingView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/LoadingView.xaml
index f1e54d2fc4..d1f862c464 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/LoadingView.xaml
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/LoadingView.xaml
@@ -52,7 +52,7 @@
-
+
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/MainPageView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/MainPageView.xaml
index e1f5ad7101..f484544cf6 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/MainPageView.xaml
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/MainPageView.xaml
@@ -75,7 +75,7 @@
-
+
-
+
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/RepoConfigView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/RepoConfigView.xaml
index ff6ffb1a6a..bc2c11c908 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/RepoConfigView.xaml
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/RepoConfigView.xaml
@@ -32,7 +32,7 @@
-
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SetupFlowPage.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/SetupFlowPage.xaml
index 3eb68014a7..79e5e95a25 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/SetupFlowPage.xaml
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SetupFlowPage.xaml
@@ -4,9 +4,7 @@
+ behaviors:NavigationViewHeaderBehavior.HeaderMode="Never">
-
+
@@ -83,6 +79,7 @@
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SetupTargetView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/SetupTargetView.xaml
index 2e2137a37c..fd65447757 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/SetupTargetView.xaml
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SetupTargetView.xaml
@@ -231,8 +231,8 @@
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
@@ -267,11 +268,11 @@
-
-
+
+
@@ -311,138 +312,139 @@
Command="{x:Bind ViewModel.GoToDashboardCommand, Mode=OneWay}"
Style="{StaticResource AccentButtonStyle}"
Margin="0, 50, 0, 0"/>
+
+
+
-
-
-
-
-
-
- 0
-
-
-
-
-
+
+
+
+ 0
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
- Installation Notes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+ Installation Notes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
From 39be39b6e81ac5e7b98c76c57dceb547be396bf6 Mon Sep 17 00:00:00 2001
From: Kristen Schau <47155823+krschau@users.noreply.github.com>
Date: Wed, 20 Mar 2024 14:05:10 -0400
Subject: [PATCH 013/121] Move Extensions page to NavigationView footer (#2431)
---
src/NavConfig.jsonc | 7 -------
src/Services/PageService.cs | 3 +--
src/Views/ShellPage.xaml | 9 ++++++++-
.../Extensions/PageExtensions.cs | 1 +
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/NavConfig.jsonc b/src/NavConfig.jsonc
index 4d570e97dc..d4c327017f 100644
--- a/src/NavConfig.jsonc
+++ b/src/NavConfig.jsonc
@@ -18,13 +18,6 @@
"viewModelFullName": "DevHome.SetupFlow.ViewModels.SetupFlowViewModel",
"icon": "f156"
},
- {
- "identity": "DevHome.ExtensionLibrary",
- "assembly": "DevHome.ExtensionLibrary",
- "viewFullName": "DevHome.ExtensionLibrary.Views.ExtensionLibraryView",
- "viewModelFullName": "DevHome.ExtensionLibrary.ViewModels.ExtensionLibraryViewModel",
- "icon": "ea86"
- },
{
"experimentalFeatureIdentity": "EnvironmentsManagementPage",
"identity": "DevHome.Environments",
diff --git a/src/Services/PageService.cs b/src/Services/PageService.cs
index dbe3a3e8a4..e37fa384b9 100644
--- a/src/Services/PageService.cs
+++ b/src/Services/PageService.cs
@@ -41,9 +41,8 @@ where assembly.GetName().Name == tool.Assembly
}
}
- // Configure other pages
+ // Configure footer pages
Configure();
-
this.ConfigureExtensionLibraryPages();
this.ConfigureSettingsPages();
diff --git a/src/Views/ShellPage.xaml b/src/Views/ShellPage.xaml
index d5df701413..37b0b4086f 100644
--- a/src/Views/ShellPage.xaml
+++ b/src/Views/ShellPage.xaml
@@ -62,11 +62,18 @@
-
+
+
+
+
+
+
diff --git a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs
index 07131df620..cfd71e3e81 100644
--- a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs
+++ b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Extensions/PageExtensions.cs
@@ -11,6 +11,7 @@ public static class PageExtensions
{
public static void ConfigureExtensionLibraryPages(this IPageService pageService)
{
+ pageService.Configure();
pageService.Configure();
}
}
From 96810ec7c7915accbef47479445f355536dd04a3 Mon Sep 17 00:00:00 2001
From: Kristen Schau <47155823+krschau@users.noreply.github.com>
Date: Wed, 20 Mar 2024 14:09:45 -0400
Subject: [PATCH 014/121] Update theme of Add Widget dialog when system theme
changes (#2407)
---
.../ViewModels/AddWidgetViewModel.cs | 32 ++++++++++++--
.../Views/AddWidgetDialog.xaml | 7 ++--
.../Views/AddWidgetDialog.xaml.cs | 42 +++++++++++++------
.../Views/DashboardView.xaml.cs | 3 +-
4 files changed, 62 insertions(+), 22 deletions(-)
diff --git a/tools/Dashboard/DevHome.Dashboard/ViewModels/AddWidgetViewModel.cs b/tools/Dashboard/DevHome.Dashboard/ViewModels/AddWidgetViewModel.cs
index 80c697a83b..ae700c31b7 100644
--- a/tools/Dashboard/DevHome.Dashboard/ViewModels/AddWidgetViewModel.cs
+++ b/tools/Dashboard/DevHome.Dashboard/ViewModels/AddWidgetViewModel.cs
@@ -3,8 +3,9 @@
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using DevHome.Contracts.Services;
using DevHome.Dashboard.Services;
-using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
using Microsoft.Windows.Widgets.Hosts;
@@ -13,6 +14,7 @@ namespace DevHome.Dashboard.ViewModels;
public partial class AddWidgetViewModel : ObservableObject
{
private readonly IWidgetScreenshotService _widgetScreenshotService;
+ private readonly IThemeSelectorService _themeSelectorService;
[ObservableProperty]
private string _widgetDisplayTitle;
@@ -26,14 +28,20 @@ public partial class AddWidgetViewModel : ObservableObject
[ObservableProperty]
private bool _pinButtonVisibility;
- public AddWidgetViewModel(IWidgetScreenshotService widgetScreenshotService)
+ private WidgetDefinition _selectedWidgetDefinition;
+
+ public AddWidgetViewModel(
+ IWidgetScreenshotService widgetScreenshotService,
+ IThemeSelectorService themeSelectorService)
{
_widgetScreenshotService = widgetScreenshotService;
+ _themeSelectorService = themeSelectorService;
}
- public async Task SetWidgetDefinition(WidgetDefinition selectedWidgetDefinition, ElementTheme actualTheme)
+ public async Task SetWidgetDefinition(WidgetDefinition selectedWidgetDefinition)
{
- var bitmap = await _widgetScreenshotService.GetScreenshotFromCache(selectedWidgetDefinition, actualTheme);
+ _selectedWidgetDefinition = selectedWidgetDefinition;
+ var bitmap = await _widgetScreenshotService.GetScreenshotFromCache(selectedWidgetDefinition, _themeSelectorService.GetActualTheme());
WidgetDisplayTitle = selectedWidgetDefinition.DisplayTitle;
WidgetProviderDisplayTitle = selectedWidgetDefinition.ProviderDefinition.DisplayName;
@@ -50,5 +58,21 @@ public void Clear()
WidgetProviderDisplayTitle = string.Empty;
WidgetScreenshot = null;
PinButtonVisibility = false;
+ _selectedWidgetDefinition = null;
+ }
+
+ [RelayCommand]
+ private async Task UpdateThemeAsync()
+ {
+ if (_selectedWidgetDefinition != null)
+ {
+ // Update the preview image for the selected widget.
+ var theme = _themeSelectorService.GetActualTheme();
+ var bitmap = await _widgetScreenshotService.GetScreenshotFromCache(_selectedWidgetDefinition, theme);
+ WidgetScreenshot = new ImageBrush
+ {
+ ImageSource = bitmap,
+ };
+ }
}
}
diff --git a/tools/Dashboard/DevHome.Dashboard/Views/AddWidgetDialog.xaml b/tools/Dashboard/DevHome.Dashboard/Views/AddWidgetDialog.xaml
index 08b38ddcc0..1dad6f73b6 100644
--- a/tools/Dashboard/DevHome.Dashboard/Views/AddWidgetDialog.xaml
+++ b/tools/Dashboard/DevHome.Dashboard/Views/AddWidgetDialog.xaml
@@ -5,18 +5,19 @@
x:Class="DevHome.Dashboard.Views.AddWidgetDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:commonviews="using:DevHome.Common.Views"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
- mc:Ignorable="d"
Style="{StaticResource DefaultContentDialogStyle}"
SizeChanged="ContentDialog_SizeChanged">
+
+
+
+
diff --git a/tools/Dashboard/DevHome.Dashboard/Views/AddWidgetDialog.xaml.cs b/tools/Dashboard/DevHome.Dashboard/Views/AddWidgetDialog.xaml.cs
index 2c7fed0d41..642498e716 100644
--- a/tools/Dashboard/DevHome.Dashboard/Views/AddWidgetDialog.xaml.cs
+++ b/tools/Dashboard/DevHome.Dashboard/Views/AddWidgetDialog.xaml.cs
@@ -6,10 +6,10 @@
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Extensions;
+using DevHome.Contracts.Services;
using DevHome.Dashboard.Helpers;
using DevHome.Dashboard.Services;
using DevHome.Dashboard.ViewModels;
-using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
@@ -17,13 +17,13 @@
using Microsoft.UI.Xaml.Media.Imaging;
using Microsoft.UI.Xaml.Shapes;
using Microsoft.Windows.Widgets.Hosts;
+using WinUIEx;
namespace DevHome.Dashboard.Views;
public sealed partial class AddWidgetDialog : ContentDialog
{
private WidgetDefinition _selectedWidget;
- private static DispatcherQueue _dispatcher;
public WidgetDefinition AddedWidget { get; private set; }
@@ -31,10 +31,9 @@ public sealed partial class AddWidgetDialog : ContentDialog
private readonly IWidgetHostingService _hostingService;
private readonly IWidgetIconService _widgetIconService;
+ private readonly WindowEx _windowEx;
- public AddWidgetDialog(
- DispatcherQueue dispatcher,
- ElementTheme theme)
+ public AddWidgetDialog()
{
ViewModel = Application.Current.GetService();
_hostingService = Application.Current.GetService();
@@ -42,11 +41,9 @@ public AddWidgetDialog(
this.InitializeComponent();
- _dispatcher = dispatcher;
+ _windowEx = Application.Current.GetService();
- // Strange behavior: just setting the requested theme when we new-up the dialog results in
- // the wrong theme's resources being used. Setting RequestedTheme here fixes the problem.
- RequestedTheme = theme;
+ RequestedTheme = Application.Current.GetService().Theme;
}
[RelayCommand]
@@ -225,7 +222,7 @@ private async void AddWidgetNavigationView_SelectionChanged(
if (selectedTag as WidgetDefinition is WidgetDefinition selectedWidgetDefinition)
{
_selectedWidget = selectedWidgetDefinition;
- await ViewModel.SetWidgetDefinition(selectedWidgetDefinition, ActualTheme);
+ await ViewModel.SetWidgetDefinition(selectedWidgetDefinition);
}
else if (selectedTag as WidgetProviderDefinition is not null)
{
@@ -233,6 +230,23 @@ private async void AddWidgetNavigationView_SelectionChanged(
}
}
+ [RelayCommand]
+ private async Task UpdateThemeAsync()
+ {
+ // Update the icons for each available widget listed.
+ foreach (var providerItem in AddWidgetNavigationView.MenuItems.OfType())
+ {
+ foreach (var widgetItem in providerItem.MenuItems.OfType())
+ {
+ if (widgetItem.Tag is WidgetDefinition widgetDefinition)
+ {
+ var image = await _widgetIconService.GetWidgetIconForThemeAsync(widgetDefinition, ActualTheme);
+ widgetItem.Content = BuildNavItem(image, widgetDefinition.DisplayTitle);
+ }
+ }
+ }
+ }
+
[RelayCommand]
private void PinButtonClick()
{
@@ -266,7 +280,7 @@ private void WidgetCatalog_WidgetDefinitionDeleted(WidgetCatalog sender, WidgetD
{
var deletedDefinitionId = args.DefinitionId;
- _dispatcher.TryEnqueue(() =>
+ _windowEx.DispatcherQueue.TryEnqueue(() =>
{
// If we currently have the deleted widget open, un-select it.
if (_selectedWidget is not null &&
@@ -279,9 +293,9 @@ private void WidgetCatalog_WidgetDefinitionDeleted(WidgetCatalog sender, WidgetD
// Remove the deleted WidgetDefinition from the list of available widgets.
var menuItems = AddWidgetNavigationView.MenuItems;
- foreach (var providerItem in menuItems.Cast())
+ foreach (var providerItem in menuItems.OfType())
{
- foreach (var widgetItem in providerItem.MenuItems.Cast())
+ foreach (var widgetItem in providerItem.MenuItems.OfType())
{
if (widgetItem.Tag is WidgetDefinition tagDefinition)
{
@@ -301,6 +315,8 @@ private void WidgetCatalog_WidgetDefinitionDeleted(WidgetCatalog sender, WidgetD
Log.Logger()?.ReportError("AddWidgetDialog", $"WidgetCatalog_WidgetDefinitionDeleted found no available widgets.");
}
}
+
+ return;
}
}
}
diff --git a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs
index 1317cb488b..694fb02273 100644
--- a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs
+++ b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs
@@ -359,11 +359,10 @@ public async Task GoToWidgetsInStoreAsync()
[RelayCommand]
public async Task AddWidgetClickAsync()
{
- var dialog = new AddWidgetDialog(_dispatcher, ActualTheme)
+ var dialog = new AddWidgetDialog()
{
// XamlRoot must be set in the case of a ContentDialog running in a Desktop app.
XamlRoot = this.XamlRoot,
- RequestedTheme = this.ActualTheme,
};
_ = await dialog.ShowAsync();
From 02e94fd5f3f97d60b6aefc45580ebee1b660a257 Mon Sep 17 00:00:00 2001
From: James Alickolli <32421608+licon4812@users.noreply.github.com>
Date: Thu, 21 Mar 2024 07:32:26 +1100
Subject: [PATCH 015/121] Update HyperVVirtualMachine.cs (#2437)
---
.../src/HyperVExtension/Models/HyperVVirtualMachine.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs b/HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs
index 4d1cc989da..8cf3e8310b 100644
--- a/HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs
+++ b/HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs
@@ -527,7 +527,7 @@ public IAsyncOperation> GetComputeSystemPrope
{
ComputeSystemProperty.Create(ComputeSystemPropertyKind.CpuCount, ProcessorCount),
ComputeSystemProperty.Create(ComputeSystemPropertyKind.AssignedMemorySizeInBytes, MemoryAssigned),
- ComputeSystemProperty.Create(ComputeSystemPropertyKind.AssignedMemorySizeInBytes, totalDiskSize),
+ ComputeSystemProperty.Create(ComputeSystemPropertyKind.StorageSizeInBytes, totalDiskSize),
ComputeSystemProperty.Create(ComputeSystemPropertyKind.UptimeIn100ns, Uptime),
ComputeSystemProperty.CreateCustom(ParentCheckpointName, _stringResource.GetLocalized(_currentCheckpointKey), null),
};
From 49933a93894edd4405fe58aee23841d33d321400 Mon Sep 17 00:00:00 2001
From: sshilov7 <51001703+sshilov7@users.noreply.github.com>
Date: Wed, 20 Mar 2024 14:47:54 -0700
Subject: [PATCH 016/121] [Hyper-V extension] Use OOP WinGet object. Update or
install Desktop App Installer package during Hyper-V Configure workflow if
needed. (#2424)
---
.../DevSetupAgent/Requests/RequestFactory.cs | 3 -
.../ApplyConfigurationProgressWatcher.cs | 9 +-
.../ApplyConfigurationResult.cs | 6 +-
.../DevSetupEngine/ConfigurationFileHelper.cs | 349 ++++++++++++++----
.../src/DevSetupEngine/DevSetupEngine.csproj | 21 +-
.../PackageOperationException.cs | 22 ++
6 files changed, 337 insertions(+), 73 deletions(-)
create mode 100644 HyperVExtension/src/DevSetupEngine/PackageOperationException.cs
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/RequestFactory.cs b/HyperVExtension/src/DevSetupAgent/Requests/RequestFactory.cs
index 5a8ef75383..a60d7934c3 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/RequestFactory.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/RequestFactory.cs
@@ -1,10 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.ServiceModel.Channels;
-using System.Text.Json;
using System.Text.Json.Nodes;
-using Windows.Storage;
namespace HyperVExtension.DevSetupAgent;
diff --git a/HyperVExtension/src/DevSetupEngine/ApplyConfigurationProgressWatcher.cs b/HyperVExtension/src/DevSetupEngine/ApplyConfigurationProgressWatcher.cs
index 174362c222..80c00d24ea 100644
--- a/HyperVExtension/src/DevSetupEngine/ApplyConfigurationProgressWatcher.cs
+++ b/HyperVExtension/src/DevSetupEngine/ApplyConfigurationProgressWatcher.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using HyperVExtension.DevSetupEngine.ConfigurationResultTypes;
-using Microsoft.CodeAnalysis.Emit;
using Windows.Foundation;
using DevSetupEngineTypes = Microsoft.Windows.DevHome.DevSetupEngine;
@@ -25,6 +24,14 @@ public ApplyConfigurationProgressWatcher(IProgress operation, WinGet.ConfigurationSetChangeData data)
{
if (_isFirstProgress)
diff --git a/HyperVExtension/src/DevSetupEngine/ApplyConfigurationResult.cs b/HyperVExtension/src/DevSetupEngine/ApplyConfigurationResult.cs
index be07d18dd4..50d15ecb66 100644
--- a/HyperVExtension/src/DevSetupEngine/ApplyConfigurationResult.cs
+++ b/HyperVExtension/src/DevSetupEngine/ApplyConfigurationResult.cs
@@ -97,7 +97,7 @@ public OpenConfigurationSetResult(Exception? resultCode, string field, string fi
[ComDefaultInterface(typeof(IConfigurationUnit))]
public class ConfigurationUnit : IConfigurationUnit
{
- public ConfigurationUnit(string type, string identifier, DevSetupEngineTypes.ConfigurationUnitState state, bool isGroup, IList? units, ValueSet settings, ConfigurationUnitIntent intent)
+ public ConfigurationUnit(string type, string identifier, DevSetupEngineTypes.ConfigurationUnitState state, bool isGroup, IList? units, ValueSet? settings, ConfigurationUnitIntent intent)
{
Type = type;
Identifier = identifier;
@@ -193,14 +193,14 @@ public ApplyConfigurationUnitResult(IConfigurationUnit unit, ConfigurationUnitSt
[ComDefaultInterface(typeof(IApplyConfigurationSetResult))]
public class ApplyConfigurationSetResult : IApplyConfigurationSetResult
{
- public ApplyConfigurationSetResult(Exception? resultCode, IReadOnlyList unitResults)
+ public ApplyConfigurationSetResult(Exception? resultCode, IReadOnlyList? unitResults)
{
ResultCode = resultCode;
UnitResults = unitResults;
}
// Results for each configuration unit in the set.
- public IReadOnlyList UnitResults { get; }
+ public IReadOnlyList? UnitResults { get; }
// The overall result from applying the configuration set.
public Exception? ResultCode { get; }
diff --git a/HyperVExtension/src/DevSetupEngine/ConfigurationFileHelper.cs b/HyperVExtension/src/DevSetupEngine/ConfigurationFileHelper.cs
index 4a98bdccf6..106fab2d87 100644
--- a/HyperVExtension/src/DevSetupEngine/ConfigurationFileHelper.cs
+++ b/HyperVExtension/src/DevSetupEngine/ConfigurationFileHelper.cs
@@ -1,12 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Buffers;
using Microsoft.Management.Configuration;
-using Microsoft.Management.Configuration.Processor;
-using Microsoft.Management.Configuration.SetProcessorFactory;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Store.Preview.InstallControl;
+using Windows.Foundation;
using Windows.Storage.Streams;
-using WinRT;
using DevSetupEngineTypes = Microsoft.Windows.DevHome.DevSetupEngine;
using WinGet = Microsoft.Management.Configuration;
@@ -18,6 +17,8 @@ namespace HyperVExtension.DevSetupEngine;
///
public class ConfigurationFileHelper
{
+ private const string PowerShellHandlerIdentifier = "pwsh";
+
public class ApplicationResult
{
public WinGet.ApplyConfigurationSetResult Result
@@ -44,34 +45,130 @@ public ConfigurationFileHelper()
{
}
+ private static async Task InstallOrUpdateAppInstallerIfNeeded(IProgress progress)
+ {
+ const string AppInstallerPackageName = "Microsoft.DesktopAppInstaller";
+ const string AppInstallerPackageFamilyName = "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe";
+ const string AppInstallerStoreId = "9NBLGGH4NNS1";
+
+ var doInstall = false;
+ Windows.Management.Deployment.PackageManager packageManager = new();
+ var currentInstallerPackage = packageManager.FindPackagesForUser(string.Empty, AppInstallerPackageFamilyName).FirstOrDefault();
+ if (currentInstallerPackage == null)
+ {
+ doInstall = true;
+ }
+ else
+ {
+ if (!IsAppInstallerUpdateNeeded(currentInstallerPackage))
+ {
+ return;
+ }
+ }
+
+ AppInstallManager installManager = new();
+ var progressWatcher = new ApplyConfigurationProgressWatcher(progress);
+ var configurationSetChangeData = GetConfigurationSetChangeData(AppInstallerPackageName, DevSetupEngineTypes.ConfigurationUnitState.Pending, string.Empty);
+ progressWatcher.Report(configurationSetChangeData);
+
+ AppInstallItem? installItem;
+ if (doInstall)
+ {
+ installItem = await installManager.StartAppInstallAsync(AppInstallerStoreId, null, true, false);
+ }
+ else
+ {
+ installItem = await installManager.UpdateAppByPackageFamilyNameAsync(AppInstallerPackageFamilyName);
+ }
+
+ if (installItem == null)
+ {
+ throw new PackageOperationException(PackageOperationException.ErrorCode.DevSetupErrorUpdateNotApplicable, $"Failed to search for {AppInstallerPackageName} updates");
+ }
+
+ CancellationTokenSource cancellationToken = new();
+ TypedEventHandler completedHandler = (sender, args) =>
+ {
+ configurationSetChangeData = GetConfigurationSetChangeData(AppInstallerPackageName, DevSetupEngineTypes.ConfigurationUnitState.Completed);
+ progressWatcher.Report(configurationSetChangeData);
+ cancellationToken.Cancel();
+ };
+
+ TypedEventHandler statusChangedHandler = (sender, args) =>
+ {
+ configurationSetChangeData = GetConfigurationSetChangeData(AppInstallerPackageName, DevSetupEngineTypes.ConfigurationUnitState.InProgress);
+ progressWatcher.Report(configurationSetChangeData);
+ };
+
+ try
+ {
+ installItem.InstallInProgressToastNotificationMode = AppInstallationToastNotificationMode.NoToast;
+ installItem.CompletedInstallToastNotificationMode = AppInstallationToastNotificationMode.NoToast;
+ installItem.Completed += completedHandler;
+ installItem.StatusChanged += statusChangedHandler;
+
+#if DEBUG
+ // In debug mode report more often and with extended description.
+ var installStatus = installItem.GetCurrentStatus();
+ cancellationToken.CancelAfter(TimeSpan.FromMinutes(15));
+ while (!installStatus.ReadyForLaunch &&
+ !cancellationToken.IsCancellationRequested &&
+ (installStatus.InstallState != AppInstallState.Error) &&
+ (installStatus.InstallState != AppInstallState.Canceled))
+ {
+ installStatus = installItem.GetCurrentStatus();
+ var description = GetInstallStatusDescription(installStatus);
+ configurationSetChangeData = GetConfigurationSetChangeData(AppInstallerPackageName, DevSetupEngineTypes.ConfigurationUnitState.InProgress, description);
+ progressWatcher.Report(configurationSetChangeData);
+ await Task.Delay(5000);
+ installStatus = installItem.GetCurrentStatus();
+ }
+#else
+ try
+ {
+ await Task.Delay(TimeSpan.FromMinutes(15), cancellationToken.Token);
+ }
+ catch (TaskCanceledException)
+ {
+ // Expected
+ }
+
+ var installStatus = installItem.GetCurrentStatus();
+ Logging.Logger()?.ReportInfo($"{AppInstallerPackageName} installation status: {installStatus}");
+ if (installStatus.InstallState != AppInstallState.Completed)
+ {
+ throw new PackageOperationException(PackageOperationException.ErrorCode.DevSetupErrorMsStoreInstallFailed, $"Failed to install {AppInstallerPackageName} updates");
+ }
+#endif
+ }
+ finally
+ {
+ installItem.Completed -= completedHandler;
+ installItem.StatusChanged -= statusChangedHandler;
+ }
+ }
+
///
/// Open configuration set from the provided .
///
/// DSC configuration file content
- private ConfigurationResultTypes.OpenConfigurationSetResult OpenConfigurationSet(string content)
+ private async Task OpenConfigurationSet(string content)
{
try
{
- var modulesPath = Path.Combine(AppContext.BaseDirectory, @"runtimes\win\lib\net8.0\Modules");
- var externalModulesPath = Path.Combine(AppContext.BaseDirectory, "ExternalModules");
+ ConfigurationStaticFunctions config = new();
+ var factory = await config.CreateConfigurationSetProcessorFactoryAsync(PowerShellHandlerIdentifier).AsTask();
- PowerShellConfigurationSetProcessorFactory pwshFactory = new PowerShellConfigurationSetProcessorFactory();
- pwshFactory.Policy = PowerShellConfigurationProcessorPolicy.Unrestricted;
- pwshFactory.AdditionalModulePaths = new List() { modulesPath, externalModulesPath };
- Logging.Logger()?.ReportInfo($"Additional module paths: {string.Join(", ", pwshFactory.AdditionalModulePaths)}");
-
- _processor = new ConfigurationProcessor(pwshFactory);
- _processor.MinimumLevel = WinGet.DiagnosticLevel.Verbose;
- _processor.Diagnostics += (sender, args) => LogConfigurationDiagnostics(args);
- _processor.Caller = nameof(DevSetupEngine);
+ // Create and configure the configuration processor.
+ var processor = config.CreateConfigurationProcessor(factory);
+ processor.Caller = nameof(DevSetupEngine);
+ processor.Diagnostics += (sender, args) => LogConfigurationDiagnostics(args);
+ processor.MinimumLevel = DiagnosticLevel.Verbose;
+ _processor = processor;
var inputStream = StringToStream(content);
var openResult = _processor.OpenConfigurationSet(inputStream);
- _configSet = openResult.Set;
- if (_configSet == null)
- {
- throw new OpenConfigurationSetException(openResult);
- }
+ _configSet = openResult.Set ?? throw new OpenConfigurationSetException(openResult);
return new ConfigurationResultTypes.OpenConfigurationSetResult(openResult.ResultCode, openResult.Field, openResult.Value, openResult.Line, openResult.Column);
}
@@ -97,63 +194,81 @@ private ConfigurationResultTypes.OpenConfigurationSetResult OpenConfigurationSet
private async Task ApplyConfigurationSetAsync(IProgress progress)
{
- if (_processor == null || _configSet == null)
+ try
{
- throw new InvalidOperationException();
- }
-
- Logging.Logger()?.ReportInfo("Starting to apply configuration set");
- var applySetOperation = _processor.ApplySetAsync(_configSet, WinGet.ApplyConfigurationSetFlags.None);
- var progressWatcher = new ApplyConfigurationProgressWatcher(progress);
- applySetOperation.Progress += progressWatcher.Watcher;
- var result = await applySetOperation;
+ if (_processor == null || _configSet == null)
+ {
+ throw new InvalidOperationException();
+ }
- Logging.Logger()?.ReportInfo($"Apply configuration finished. HResult: {result.ResultCode?.HResult}");
+ Logging.Logger()?.ReportInfo("Starting to apply configuration set");
+ var applySetOperation = _processor.ApplySetAsync(_configSet, WinGet.ApplyConfigurationSetFlags.None);
+ var progressWatcher = new ApplyConfigurationProgressWatcher(progress);
+ applySetOperation.Progress += progressWatcher.Watcher;
+ var result = await applySetOperation;
- var unitResults = new List();
- foreach (var unitResult in result.UnitResults)
- {
- var unit = new ConfigurationResultTypes.ConfigurationUnit(
- unitResult.Unit.Type,
- unitResult.Unit.Identifier,
- (DevSetupEngineTypes.ConfigurationUnitState)unitResult.Unit.State,
- false,
- null,
- unitResult.Unit.Settings,
- (DevSetupEngineTypes.ConfigurationUnitIntent)unitResult.Unit.Intent);
+ Logging.Logger()?.ReportInfo($"Apply configuration finished. HResult: {result.ResultCode?.HResult}");
- var resultInfo = new ConfigurationResultTypes.ConfigurationUnitResultInformation(
- unitResult.ResultInformation.ResultCode,
- unitResult.ResultInformation.Description,
- unitResult.ResultInformation.Details,
- (DevSetupEngineTypes.ConfigurationUnitResultSource)unitResult.ResultInformation.ResultSource);
+ var unitResults = new List();
+ foreach (var unitResult in result.UnitResults)
+ {
+ var unit = new ConfigurationResultTypes.ConfigurationUnit(
+ unitResult.Unit.Type,
+ unitResult.Unit.Identifier,
+ (DevSetupEngineTypes.ConfigurationUnitState)unitResult.Unit.State,
+ false,
+ null,
+ unitResult.Unit.Settings,
+ (DevSetupEngineTypes.ConfigurationUnitIntent)unitResult.Unit.Intent);
+
+ var resultInfo = new ConfigurationResultTypes.ConfigurationUnitResultInformation(
+ unitResult.ResultInformation.ResultCode,
+ unitResult.ResultInformation.Description,
+ unitResult.ResultInformation.Details,
+ (DevSetupEngineTypes.ConfigurationUnitResultSource)unitResult.ResultInformation.ResultSource);
+
+ var configurationUnitResult = new ConfigurationResultTypes.ApplyConfigurationUnitResult(
+ unit,
+ (DevSetupEngineTypes.ConfigurationUnitState)unitResult.State,
+ unitResult.PreviouslyInDesiredState,
+ unitResult.RebootRequired,
+ resultInfo);
+
+ unitResults.Add(configurationUnitResult);
+ }
- var configurationUnitResult = new ConfigurationResultTypes.ApplyConfigurationUnitResult(
- unit,
- (DevSetupEngineTypes.ConfigurationUnitState)unitResult.State,
- unitResult.PreviouslyInDesiredState,
- unitResult.RebootRequired,
- resultInfo);
+ var applyConfigurationSetResult = new ConfigurationResultTypes.ApplyConfigurationSetResult(result.ResultCode, unitResults);
- unitResults.Add(configurationUnitResult);
+ return applyConfigurationSetResult;
+ }
+ catch (Exception ex)
+ {
+ return new ConfigurationResultTypes.ApplyConfigurationSetResult(ex, null);
}
-
- var applyConfigurationSetResult = new ConfigurationResultTypes.ApplyConfigurationSetResult(result.ResultCode, unitResults);
-
- return applyConfigurationSetResult;
}
public async Task ApplyConfigurationAsync(string content, IProgress progress)
{
- var openConfigurationSetResult = OpenConfigurationSet(content);
- if (openConfigurationSetResult.ResultCode != null)
+ DevSetupEngineTypes.IOpenConfigurationSetResult? openConfigurationSetResult = default;
+ DevSetupEngineTypes.IApplyConfigurationSetResult? applyConfigurationResult = default;
+ try
{
- return new ConfigurationResultTypes.ApplyConfigurationResult(openConfigurationSetResult.ResultCode, string.Empty, openConfigurationSetResult, null);
- }
+ await InstallOrUpdateAppInstallerIfNeeded(progress);
- var applyConfigurationSetResult = await ApplyConfigurationSetAsync(progress);
+ openConfigurationSetResult = await OpenConfigurationSet(content);
+ if (openConfigurationSetResult.ResultCode != null)
+ {
+ return new ConfigurationResultTypes.ApplyConfigurationResult(openConfigurationSetResult.ResultCode, string.Empty, openConfigurationSetResult, null);
+ }
- return new ConfigurationResultTypes.ApplyConfigurationResult(applyConfigurationSetResult.ResultCode, string.Empty, openConfigurationSetResult, applyConfigurationSetResult);
+ var applyConfigurationSetResult = await ApplyConfigurationSetAsync(progress);
+
+ return new ConfigurationResultTypes.ApplyConfigurationResult(applyConfigurationSetResult.ResultCode, string.Empty, openConfigurationSetResult, applyConfigurationSetResult);
+ }
+ catch (Exception ex)
+ {
+ return new ConfigurationResultTypes.ApplyConfigurationResult(ex, ex.Message, openConfigurationSetResult, applyConfigurationResult);
+ }
}
private void LogConfigurationDiagnostics(WinGet.IDiagnosticInformation diagnosticInformation)
@@ -201,4 +316,110 @@ private IInputStream StringToStream(string str)
result.Seek(0);
return result;
}
+
+ ///
+ /// Check if the App Installer needs to be updated.
+ ///
+ /// Microsoft.DesktopAppInstaller package
+ /// true if current Microsoft.DesktopAppInstaller package version is less than 1.22.10661.0
+ private static bool IsAppInstallerUpdateNeeded(Package currentInstallerPackage)
+ {
+ var packageVersion = currentInstallerPackage.Id.Version;
+ const int minMajor = 1;
+ const int minMinor = 22;
+ const int minBuild = 10661;
+
+ if (packageVersion.Major > minMajor)
+ {
+ return false;
+ }
+ else if (packageVersion.Major < minMajor)
+ {
+ return true;
+ }
+
+ if (packageVersion.Minor > minMinor)
+ {
+ return false;
+ }
+ else if (packageVersion.Minor < minMinor)
+ {
+ return true;
+ }
+
+ if (packageVersion.Build > minBuild)
+ {
+ return false;
+ }
+ else if (packageVersion.Build < minBuild)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static ConfigurationResultTypes.ConfigurationSetChangeData GetConfigurationSetChangeData(string identifier, DevSetupEngineTypes.ConfigurationUnitState unitState, string description = "")
+ {
+ var resultInfo = new ConfigurationResultTypes.ConfigurationUnitResultInformation(
+ null,
+ description,
+ string.Empty,
+ DevSetupEngineTypes.ConfigurationUnitResultSource.Precondition);
+
+ var configurationUnit = new ConfigurationResultTypes.ConfigurationUnit(
+ string.Empty,
+ identifier,
+ unitState,
+ false,
+ null,
+ null,
+ DevSetupEngineTypes.ConfigurationUnitIntent.Apply);
+
+ return new ConfigurationResultTypes.ConfigurationSetChangeData(
+ DevSetupEngineTypes.ConfigurationSetChangeEventType.UnitStateChanged,
+ DevSetupEngineTypes.ConfigurationSetState.Unknown,
+ unitState,
+ resultInfo,
+ configurationUnit);
+ }
+
+#if DEBUG
+ private static string GetInstallStatusDescription(AppInstallStatus installStatus)
+ {
+ switch (installStatus.InstallState)
+ {
+ case AppInstallState.Completed:
+ return "Status: Completed";
+ case AppInstallState.ReadyToDownload:
+ return "Status: Ready To Download";
+ case AppInstallState.Starting:
+ return "Status: Starting";
+ case AppInstallState.Installing:
+ return $"Status: Installing ({installStatus.PercentComplete}%)";
+ case AppInstallState.Downloading:
+ return $"Status: Downloading ({installStatus.PercentComplete}%)";
+ case AppInstallState.AcquiringLicense:
+ return "Status: Acquiring license";
+ case AppInstallState.Pending:
+ return "Status: Pending";
+ case AppInstallState.RestoringData:
+ return "Status: Restoring Data";
+ case AppInstallState.Paused:
+ return "Status: Paused";
+ case AppInstallState.Error:
+ return "Status: Error";
+ case AppInstallState.Canceled:
+ return "Status: Canceled";
+ case AppInstallState.PausedLowBattery:
+ return "Status: Paused low battery";
+ case AppInstallState.PausedWiFiRecommended:
+ return "Status: Paused WiFi Recommended";
+ case AppInstallState.PausedWiFiRequired:
+ return "Status: Paused WiFi Required";
+ default:
+ return "Status: Unknown";
+ }
+ }
+#endif
}
diff --git a/HyperVExtension/src/DevSetupEngine/DevSetupEngine.csproj b/HyperVExtension/src/DevSetupEngine/DevSetupEngine.csproj
index b77fc14459..6e409efa88 100644
--- a/HyperVExtension/src/DevSetupEngine/DevSetupEngine.csproj
+++ b/HyperVExtension/src/DevSetupEngine/DevSetupEngine.csproj
@@ -29,14 +29,31 @@
-
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+
+ NU1701
+ true
+ none
+
+
+ True
+
diff --git a/HyperVExtension/src/DevSetupEngine/PackageOperationException.cs b/HyperVExtension/src/DevSetupEngine/PackageOperationException.cs
new file mode 100644
index 0000000000..ea9bcfabc7
--- /dev/null
+++ b/HyperVExtension/src/DevSetupEngine/PackageOperationException.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.Management.Configuration;
+
+namespace HyperVExtension.DevSetupEngine;
+
+public class PackageOperationException : Exception
+{
+ public enum ErrorCode
+ {
+ DevSetupErrorUpdateNotApplicable = unchecked((int)0x8500002B),
+ DevSetupErrorMsStoreInstallFailed = unchecked((int)0x8500001E),
+ }
+
+ public PackageOperationException(ErrorCode errorCode, string message)
+ : base(message)
+ {
+ HResult = (int)errorCode;
+ Logging.Logger()?.ReportError(string.Empty, this);
+ }
+}
From 657e9b983f8c92ec50db2222c7cfe9bb3846ff21 Mon Sep 17 00:00:00 2001
From: Kristen Schau <47155823+krschau@users.noreply.github.com>
Date: Thu, 21 Mar 2024 10:54:58 -0400
Subject: [PATCH 017/121] Fix ExtensionLibrary's Uninstall MenuFlyoutItem
layout (#2441)
---
.../DevHome.ExtensionLibrary/Views/ExtensionLibraryView.xaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Views/ExtensionLibraryView.xaml b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Views/ExtensionLibraryView.xaml
index 20edc373a4..67df3b9c14 100644
--- a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Views/ExtensionLibraryView.xaml
+++ b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/Views/ExtensionLibraryView.xaml
@@ -83,7 +83,6 @@
From 4fe92fa0fdb2f0c3bea3c4b906241e85c21012e4 Mon Sep 17 00:00:00 2001
From: Darren Hoehna
Date: Thu, 21 Mar 2024 10:02:00 -0700
Subject: [PATCH 018/121] Merge searching into main. (#2443)
* Adding searching capability to the repo tool (#2245)
* Re-adding lost changes
* WIP
* Minor tweaks
* Cleaning up code.
* Fixing code issues with new()
* Reverting SDK version.
* Reverting idl change because it is another PR.
* Reverting package.appxmanifest change
* Adding search term placeholder text
* Removing a method. Using GetValuesFor
* Removing a space
* Moving QI to where it is used
---------
Co-authored-by: Darren Hoehna
* Comment changes. (#2310)
* Re-adding lost changes
* WIP
* Minor tweaks
* Cleaning up code.
* Fixing code issues with new()
* Reverting SDK version.
* Reverting idl change because it is another PR.
* Reverting package.appxmanifest change
* Adding search term placeholder text
* Removing a method. Using GetValuesFor
* Removing a space
* Moving QI to where it is used
* Comment changes
---------
Co-authored-by: Darren Hoehna
* FIxing some errors. Making the UI closer to the mocks> (#2326)
Co-authored-by: Darren Hoehna
* addRepo improvements (#2298)
* USing tags
* Can clone repos again.
* Changing visibility to bool.
* More changes
* Account combobox is reset.
* Adding some comments.
* Combobox placeholder
* Final touches
* Fixing a comment.
* Fixing SDk version
* Ignoring a test
* Update tools/SetupFlow/DevHome.SetupFlow/ViewModels/AddRepoViewModel.cs
Co-authored-by: Kristen Schau <47155823+krschau@users.noreply.github.com>
* Update tools/SetupFlow/DevHome.SetupFlow/ViewModels/AddRepoViewModel.cs
Co-authored-by: Kristen Schau <47155823+krschau@users.noreply.github.com>
* Update tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml
Co-authored-by: Kristen Schau <47155823+krschau@users.noreply.github.com>
* Changes
* Removing prefixes for uid
* Moving more things into the ViewModel.
* Getting loginUI and provider name not null.
* Ignoring anotehr test because making a new frame throws an exception.
* Adding -async
---------
Co-authored-by: Darren Hoehna
Co-authored-by: Kristen Schau <47155823+krschau@users.noreply.github.com>
* Enabling Search inputs with IRepositoryProvider (#2244)
* Adding IRepositoryProvider2
* Adding a space between the >'s
* Modifying based on feedback.
* Moving around arguments
* Changes based on semi-API review
* Adding implementation
* HOlding onto the options
* Copying a com array
* Changing a name
* Back to a working build.
* WIP
* eeeyyy, it works. Now need to add some smaller changes
* Cleaning up code
* Works and looks good
* Adding comments
* Fixing a typo
* Adding locks. Getting search to work with one provider
* Changing back to IIterable
* Changing variable names
* Adding a comment.
* Adding another QI. Removing duplicate code.
* Addressing comments.
* Updating version
* Removing plural
---------
Co-authored-by: Darren Hoehna
* Updating version
* Changing version
---------
Co-authored-by: Darren Hoehna
Co-authored-by: Kristen Schau <47155823+krschau@users.noreply.github.com>
---
.../HyperVExtension/HyperVExtension.csproj | 2 +-
common/DevHome.Common.csproj | 2 +-
.../RepositoryResult.cpp | 3 +-
.../RepositoryUriSupportResult.cpp | 2 +-
.../DevHome.SetupFlow/Models/Common.cs | 1 +
.../Models/RepositoryProvider.cs | 147 +++++-
.../Models/RepositoryProviders.cs | 52 +-
.../Models/RepositorySearchInformation.cs | 22 +
.../ViewModels/AddRepoViewModel.cs | 481 ++++++++++++++----
.../ViewModels/FolderPickerViewModel.cs | 9 +-
.../Views/AddRepoDialog.xaml | 71 ++-
.../Views/AddRepoDialog.xaml.cs | 65 ++-
12 files changed, 713 insertions(+), 144 deletions(-)
create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Models/RepositorySearchInformation.cs
diff --git a/HyperVExtension/src/HyperVExtension/HyperVExtension.csproj b/HyperVExtension/src/HyperVExtension/HyperVExtension.csproj
index 675b8c3d49..1e45238da5 100644
--- a/HyperVExtension/src/HyperVExtension/HyperVExtension.csproj
+++ b/HyperVExtension/src/HyperVExtension/HyperVExtension.csproj
@@ -17,7 +17,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/common/DevHome.Common.csproj b/common/DevHome.Common.csproj
index 3cf6850d84..1c3d3b33dd 100644
--- a/common/DevHome.Common.csproj
+++ b/common/DevHome.Common.csproj
@@ -31,7 +31,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoryResult.cpp b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoryResult.cpp
index 3fdc462728..b3c7293ae4 100644
--- a/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoryResult.cpp
+++ b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoryResult.cpp
@@ -11,7 +11,8 @@ namespace winrt::Microsoft::Windows::DevHome::SDK::implementation
}
RepositoryResult::RepositoryResult(winrt::hresult const& e, hstring const& diagnosticText)
{
- _Result = std::make_shared(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Failure, winrt::hresult(e), winrt::to_hstring("Something went wrong"), diagnosticText);
+ _Repository = std::make_shared();
+ _Result = std::make_shared(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Failure, winrt::hresult(e), diagnosticText, diagnosticText);
}
winrt::Microsoft::Windows::DevHome::SDK::IRepository RepositoryResult::Repository()
{
diff --git a/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoryUriSupportResult.cpp b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoryUriSupportResult.cpp
index 14444e3272..7eb18d4835 100644
--- a/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoryUriSupportResult.cpp
+++ b/extensionsdk/Microsoft.Windows.DevHome.SDK/RepositoryUriSupportResult.cpp
@@ -12,7 +12,7 @@ namespace winrt::Microsoft::Windows::DevHome::SDK::implementation
RepositoryUriSupportResult::RepositoryUriSupportResult(winrt::hresult const& e, hstring const& diagnosticText)
{
- _Result = std::make_shared(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Failure, winrt::hresult(e), winrt::to_hstring("Something went wrong"), diagnosticText);
+ _Result = std::make_shared(winrt::Microsoft::Windows::DevHome::SDK::ProviderOperationStatus::Failure, winrt::hresult(e), diagnosticText, diagnosticText);
_IsSupported = false;
}
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/Common.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/Common.cs
index 55c5b55ff6..49f8a748f3 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/Common.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/Common.cs
@@ -14,5 +14,6 @@ internal enum PageKind
AddViaUrl,
AddViaAccount,
Repositories,
+ SearchFields,
}
}
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProvider.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProvider.cs
index c7b9dc3d94..e42bd5c6bf 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProvider.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProvider.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using AdaptiveCards.Rendering.WinUI3;
using DevHome.Common.Renderers;
@@ -59,8 +60,6 @@ public RepositoryProvider(IExtensionWrapper extensionWrapper)
public string ExtensionDisplayName => _extensionWrapper.Name;
- private readonly object _getRepoLock = new();
-
///
/// Starts the extension if it isn't running.
///
@@ -85,6 +84,35 @@ public IRepositoryProvider GetProvider()
return _repositoryProvider;
}
+ public string GetAskChangeSearchFieldsLabel()
+ {
+ var repositoryProvider2 = _repositoryProvider as IRepositoryProvider2;
+ return repositoryProvider2?.AskToSearchLabel ?? string.Empty;
+ }
+
+ ///
+ /// Asks the provider for search terms for querying repositories.
+ ///
+ /// The names of the search fields.
+ public List GetSearchTerms()
+ {
+ var repositoryProvider2 = _repositoryProvider as IRepositoryProvider2;
+ return repositoryProvider2?.SearchFieldNames.ToList() ?? new List();
+ }
+
+ ///
+ /// Asks the provider for a list of suggestions, given values of other search terms.
+ ///
+ /// The logged in user.
+ /// All information found in the search grid
+ /// The field to request data for
+ /// A list of names that can be used for the field. An empty list is returned if the provider isn't found
+ public List GetValuesFor(IDeveloperId developerId, Dictionary searchTerms, string fieldName)
+ {
+ var repositoryProvider2 = _repositoryProvider as IRepositoryProvider2;
+ return repositoryProvider2?.GetValuesForSearchFieldAsync(searchTerms, fieldName, developerId).AsTask().Result.ToList() ?? new List();
+ }
+
///
/// Assigns handler as the event handler for the developerIdProvider.
///
@@ -249,37 +277,118 @@ public IEnumerable GetAllLoggedInAccounts()
return developerIdsResult.DeveloperIds;
}
- ///
- /// Gets all the repositories an account has for this provider.
- ///
- /// The account to search in.
- /// A collection of repositories. May be empty
- public IEnumerable GetAllRepositories(IDeveloperId developerId)
+ public RepositorySearchInformation SearchForRepositories(IDeveloperId developerId, Dictionary searchInputs)
{
- IEnumerable repositoriesForAccount;
+ TelemetryFactory.Get().Log("RepoTool_SearchForRepos_Event", LogLevel.Critical, new GetReposEvent("CallingExtension", _repositoryProvider.DisplayName, developerId));
- lock (_getRepoLock)
+ var repoSearchInformation = new RepositorySearchInformation();
+ try
{
- if (!_repositories.TryGetValue(developerId, out repositoriesForAccount))
+ if (_repositoryProvider is IRepositoryProvider2 repositoryProvider2 &&
+ IsSearchingEnabled() && searchInputs != null)
{
- TelemetryFactory.Get().Log("RepoTool_GetAllRepos_Event", LogLevel.Critical, new GetReposEvent("CallingExtension", _repositoryProvider.DisplayName, developerId));
- var result = _repositoryProvider.GetRepositoriesAsync(developerId).AsTask().Result;
- if (result.Result.Status != ProviderOperationStatus.Success)
+ var result = repositoryProvider2.GetRepositoriesAsync(searchInputs, developerId).AsTask().Result;
+ if (result.Result.Status == ProviderOperationStatus.Success)
{
- _repositories.Add(developerId, new List());
+ repoSearchInformation.Repositories = result.Repositories;
+ repoSearchInformation.SelectionOptionsPlaceHolderText = result.SelectionOptionsName;
+ repoSearchInformation.SelectionOptionsLabel = result.SelectionOptionsLabel;
+ repoSearchInformation.SelectionOptions = result.SelectionOptions.ToList();
}
else
{
- _repositories.Add(developerId, result.Repositories);
+ Log.Logger?.ReportError(Log.Component.RepoConfig, $"Could not get repositories. Message: {result.Result.DisplayMessage}", result.Result.ExtendedError);
+ }
+ }
+ else
+ {
+ // Fallback in case this is called with IRepositoryProvider.
+ RepositoriesResult result = _repositoryProvider.GetRepositoriesAsync(developerId).AsTask().Result;
+ if (result.Result.Status == ProviderOperationStatus.Success)
+ {
+ repoSearchInformation.Repositories = result.Repositories;
+ }
+ else
+ {
+ Log.Logger?.ReportError(Log.Component.RepoConfig, $"Could not get repositories. Message: {result.Result.DisplayMessage}", result.Result.ExtendedError);
}
}
}
+ catch (AggregateException aggregateException)
+ {
+ // Because tasks can be canceled DevHome should emit different logs.
+ if (aggregateException.InnerException is OperationCanceledException)
+ {
+ Log.Logger?.ReportInfo(Log.Component.RepoConfig, $"Get Repos operation was cancalled.");
+ }
+ else
+ {
+ Log.Logger?.ReportInfo(Log.Component.RepoConfig, aggregateException.ToString());
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Logger?.ReportError(Log.Component.RepoConfig, $"Could not get repositories. Message: {ex}");
+ }
+
+ _repositories[developerId] = repoSearchInformation.Repositories;
+
+ TelemetryFactory.Get().Log("RepoTool_SearchForRepos_Event", LogLevel.Critical, new GetReposEvent("FoundRepos", _repositoryProvider.DisplayName, developerId));
+ return repoSearchInformation;
+ }
+
+ public RepositorySearchInformation GetAllRepositories(IDeveloperId developerId)
+ {
+ TelemetryFactory.Get().Log("RepoTool_GetAllRepos_Event", LogLevel.Critical, new GetReposEvent("CallingExtension", _repositoryProvider.DisplayName, developerId));
+ var repoSearchInformation = new RepositorySearchInformation();
+ try
+ {
+ var result = _repositoryProvider.GetRepositoriesAsync(developerId).AsTask().Result;
+ if (result.Result.Status == ProviderOperationStatus.Success)
+ {
+ repoSearchInformation.Repositories = result.Repositories;
+ }
+ else
+ {
+ Log.Logger?.ReportError(Log.Component.RepoConfig, $"Could not get repositories. Message: {result.Result.DisplayMessage}", result.Result.ExtendedError);
+ }
+ }
+ catch (AggregateException aggregateException)
+ {
+ // Because tasks can be canceled DevHome should emit different logs.
+ if (aggregateException.InnerException is OperationCanceledException)
+ {
+ GlobalLog.Logger?.ReportInfo($"Get Repos operation was cancalled.");
+ }
+ else
+ {
+ GlobalLog.Logger?.ReportError($"{aggregateException}");
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Logger?.ReportError(Log.Component.RepoConfig, $"Could not get repositories. Message: {ex}");
+ }
- // _repositories should have an entry for developerId by now.
- repositoriesForAccount ??= _repositories[developerId];
+ _repositories[developerId] = repoSearchInformation.Repositories;
TelemetryFactory.Get().Log("RepoTool_GetAllRepos_Event", LogLevel.Critical, new GetReposEvent("FoundRepos", _repositoryProvider.DisplayName, developerId));
+ return repoSearchInformation;
+ }
+
+ ///
+ /// Checks if
+ /// 1. _repositoryProvider is IRepositoryProvider2,
+ /// 2. if it is, calls IsSearchingSupported.
+ ///
+ /// If the extension implements IRepositoryProvider2.
+ public bool IsSearchingEnabled()
+ {
+ if (_repositoryProvider is IRepositoryProvider2 repoProviderWithSearch)
+ {
+ return repoProviderWithSearch.IsSearchingSupported;
+ }
- return repositoriesForAccount;
+ return false;
}
}
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProviders.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProviders.cs
index 64a1c16cd2..d68dec38d4 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProviders.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProviders.cs
@@ -59,6 +59,38 @@ public void StartIfNotRunning(string providerName)
}
}
+ ///
+ /// Asks the provider for search terms for querying repositories.
+ ///
+ /// The provider to ask
+ /// The names of the search fields. An empty string is returned if the provider isn't found.
+ public List GetSearchTerms(string providerName)
+ {
+ if (_providers.TryGetValue(providerName, out var repoProvider))
+ {
+ return repoProvider.GetSearchTerms();
+ }
+
+ return new();
+ }
+
+ ///
+ /// Asks the provider for a list of suggestions, given values of other search terms.
+ ///
+ /// The provider to ask
+ /// All information found in the search grid
+ /// The field to request data for
+ /// A list of names that can be used for the field. An empty list is returned if the provider isn't found
+ public List GetValuesFor(string providerName, IDeveloperId developerId, Dictionary searchTerms, string fieldName)
+ {
+ if (_providers.TryGetValue(providerName, out var repoProvider))
+ {
+ return repoProvider.GetValuesFor(developerId, searchTerms, fieldName);
+ }
+
+ return new();
+ }
+
///
/// Goes through all providers to figure out if they can make a repo from a Uri.
///
@@ -164,15 +196,31 @@ public AuthenticationExperienceKind GetAuthenticationExperienceKind(string provi
return _providers.GetValueOrDefault(providerName)?.GetAuthenticationExperienceKind() ?? AuthenticationExperienceKind.CardSession;
}
+ public RepositorySearchInformation SearchForRepos(string providerName, IDeveloperId developerId, Dictionary searchInputs)
+ {
+ Log.Logger?.ReportInfo(Log.Component.RepoConfig, $"Getting all repositories for repository provider {providerName}");
+ return _providers.GetValueOrDefault(providerName)?.SearchForRepositories(developerId, searchInputs) ?? new RepositorySearchInformation();
+ }
+
///
/// Gets all the repositories for an account and provider. The account will be logged in if they aren't already.
///
/// The specific provider. Must match the display name of a provider
/// The account to look for. May not be logged in.
/// All the repositories for an account and provider.
- public IEnumerable GetAllRepositories(string providerName, IDeveloperId developerId)
+ public RepositorySearchInformation GetAllRepositories(string providerName, IDeveloperId developerId)
{
Log.Logger?.ReportInfo(Log.Component.RepoConfig, $"Getting all repositories for repository provider {providerName}");
- return _providers.GetValueOrDefault(providerName)?.GetAllRepositories(developerId) ?? new List();
+ return _providers.GetValueOrDefault(providerName)?.GetAllRepositories(developerId) ?? new RepositorySearchInformation();
+ }
+
+ public bool IsSearchingEnabled(string providerName)
+ {
+ return _providers.GetValueOrDefault(providerName)?.IsSearchingEnabled() ?? false;
+ }
+
+ public string GetAskChangeSearchFieldsLabel(string providerName)
+ {
+ return _providers.GetValueOrDefault(providerName)?.GetAskChangeSearchFieldsLabel() ?? string.Empty;
}
}
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/RepositorySearchInformation.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/RepositorySearchInformation.cs
new file mode 100644
index 0000000000..2a891f3c36
--- /dev/null
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/RepositorySearchInformation.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Windows.DevHome.SDK;
+
+namespace DevHome.SetupFlow.Models;
+
+public class RepositorySearchInformation
+{
+ public IEnumerable Repositories { get; set; } = Enumerable.Empty();
+
+ public string SelectionOptionsPlaceHolderText { get; set; } = string.Empty;
+
+ public List SelectionOptions { get; set; } = new List();
+
+ public string SelectionOptionsLabel { get; set; } = string.Empty;
+}
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/AddRepoViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/AddRepoViewModel.cs
index 411740407a..055caac755 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/AddRepoViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/AddRepoViewModel.cs
@@ -10,7 +10,6 @@
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
-using CommunityToolkit.WinUI.Collections;
using CommunityToolkit.WinUI.Controls;
using DevHome.Common.Extensions;
using DevHome.Common.Models;
@@ -26,6 +25,7 @@
using DevHome.Telemetry;
using Microsoft.Extensions.Hosting;
using Microsoft.UI;
+using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.DevHome.SDK;
@@ -52,6 +52,15 @@ public partial class AddRepoViewModel : ObservableObject
private readonly List _previouslySelectedRepos;
+ private readonly DispatcherQueue _dispatcherQueue;
+
+ ///
+ /// Holds all the currently executing tasks to GetRepositories.
+ /// Used to match a Task against _taskToUseForResults to make sure the results of the most recently executed task
+ /// is shows in the UI.
+ ///
+ private readonly List _runningGetReposTasks = new();
+
///
/// Because logic is split between the back-end and the view model, migrating code from the view
/// in one PR to the view model is too much work.
@@ -64,6 +73,20 @@ public partial class AddRepoViewModel : ObservableObject
///
private readonly AddRepoDialog _addRepoDialog;
+ private readonly object _setRepositoriesLock = new();
+
+ private List _allRepositories = new();
+
+ ///
+ /// Hold the task of the most recently ran GetRepos request.
+ ///
+ private Task _taskToUseForResults;
+
+ ///
+ /// Used to store the search fields and their values when querying for repos.
+ ///
+ private Dictionary _repoSearchInputs = new();
+
///
/// Gets the folder picker view model.
///
@@ -128,7 +151,6 @@ public List EverythingToClone
/// Names of all accounts the user has logged into for a particular provider.
///
[ObservableProperty]
- [NotifyPropertyChangedFor(nameof(IsAccountComboBoxEnabled))]
private ObservableCollection _accounts = new();
///
@@ -141,7 +163,7 @@ public List EverythingToClone
/// All repositories currently shown on the screen.
///
[ObservableProperty]
- private ObservableCollection _repositories = new();
+ private ObservableCollection _repositoriesToDisplay = new();
///
/// Should the URL page be visible?
@@ -161,6 +183,13 @@ public List EverythingToClone
[ObservableProperty]
private bool _showRepoPage;
+ ///
+ /// If the extension implements IRepositoryProvider2 users can navigate to this page
+ /// allowing users to define a simple search query to narrow down the repos returned from the extension.
+ ///
+ [ObservableProperty]
+ private bool _shouldShowSelectingSearchTerms;
+
///
/// Should the error text be shown?
///
@@ -173,6 +202,9 @@ public List EverythingToClone
[ObservableProperty]
private bool? _isAccountToggleButtonChecked;
+ ///
+ /// Possible the user is not logged in. In that case, disable the account button.
+ ///
[ObservableProperty]
private bool _isAccountButtonEnabled;
@@ -182,35 +214,81 @@ public List EverythingToClone
[ObservableProperty]
private bool? _isUrlAccountButtonChecked;
+ ///
+ /// The text of the primary button is different on different pages.
+ ///
[ObservableProperty]
private string _primaryButtonText;
+ ///
+ /// The string to show the user if the url can't be parsed.
+ ///
[ObservableProperty]
private string _urlParsingError;
- public bool IsAccountComboBoxEnabled => Accounts.Count > 1;
-
+ ///
+ /// If the URL parsing error should be shown.
+ ///
[ObservableProperty]
private bool _shouldShowUrlError;
+ ///
+ /// If DevHome is getting repos from the extension.
+ /// Used to change the UI.
+ ///
[ObservableProperty]
private bool _isFetchingRepos;
+ ///
+ /// PRimary button should not be enabled if not all information is entered.
+ ///
[ObservableProperty]
private bool _shouldEnablePrimaryButton;
+ ///
+ /// Depending on the page shown, the primary button style will be different.
+ ///
[ObservableProperty]
private Style _styleForPrimaryButton;
+ ///
+ /// If a UI should be shown to ask theuser to log in.
+ ///
[ObservableProperty]
private bool _shouldShowLoginUi;
+ ///
+ /// For some log in scenarios, no in-house cancel button is on the UI.
+ /// In that case, add our own.
+ ///
[ObservableProperty]
private bool _shouldShowXButtonInLoginUi;
+ ///
+ /// DevHome waits when a UI prompt is open. This is used to exit the wait
+ /// early if the user cancel the log in.
+ ///
[ObservableProperty]
private bool _isCancelling;
+ ///
+ /// What to display to the left of the combobox.
+ ///
+ [ObservableProperty]
+ private string _selectionOptionsPrefix;
+
+ ///
+ /// The options a user can pick from for a granular search.
+ ///
+ [ObservableProperty]
+ private ObservableCollection _selectionOptions;
+
+ ///
+ /// The placeholder text for the selection options combobox
+ ///
+ [ObservableProperty]
+ private string _selectionOptionsPlaceholderText;
+
///
/// Used to figure out what button is pressed for the split button.
/// This determines the UI elements shown/hidden.
@@ -272,61 +350,6 @@ public async Task ChangePage(SegmentedItem selectedItem)
///
public bool IsCallingSelectRange { get; set; }
- ///
- /// Filters all repos down to any that start with text.
- /// A side-effect of filtering is that SelectionChanged fires for every selected repo but only on removal.
- /// SelectionChanged isn't fired for re-adding because repos are removed, not added. To prevent the RepoTool from forgetting the repos that were selected
- /// the flag _isFiltering is used to prevent modifications to EverythingToClone.
- /// Once filtering is done SelectRange is called on each item in EverythingToClone to re-select them.
- ///
- /// The text to use with .Contains
- public void FilterRepositories(string text)
- {
- IEnumerable filteredRepositories;
- if (text.Equals(string.Empty, StringComparison.OrdinalIgnoreCase))
- {
- filteredRepositories = _repositoriesForAccount;
- }
- else
- {
- filteredRepositories = _repositoriesForAccount
- .Where(x => x.DisplayName.Contains(text, StringComparison.OrdinalIgnoreCase));
- }
-
- _isFiltering = true;
- Repositories = new ObservableCollection(OrderRepos(filteredRepositories));
- _isFiltering = false;
- }
-
- ///
- /// Order repos in a particular order. The order is
- /// 1. User Private repos
- /// 2. Org repos
- /// 3. User Public repos.
- /// Each section is ordered by the most recently updated.
- ///
- /// The list of repos to order.
- /// An enumerable collection of items ready to be put into the ListView
- private IEnumerable OrderRepos(IEnumerable repos)
- {
- var organizationRepos = repos.Where(x => !x.OwningAccountName.Equals(SelectedAccount, StringComparison.OrdinalIgnoreCase))
- .OrderByDescending(x => x.LastUpdated)
- .Select(x => new RepoViewListItem(x));
-
- var userRepos = repos.Where(x => x.OwningAccountName.Equals(SelectedAccount, StringComparison.OrdinalIgnoreCase));
- var userPublicRepos = userRepos.Where(x => !x.IsPrivate)
- .OrderByDescending(x => x.LastUpdated)
- .Select(x => new RepoViewListItem(x));
-
- var userPrivateRepos = userRepos.Where(x => x.IsPrivate)
- .OrderByDescending(x => x.LastUpdated)
- .Select(x => new RepoViewListItem(x));
-
- return userPrivateRepos
- .Concat(organizationRepos)
- .Concat(userPublicRepos);
- }
-
///
/// Gets a value indicating whether the UI can skip the account page and switch to the repo page.
///
@@ -404,13 +427,31 @@ private void CancelButtonPressed()
[ObservableProperty]
private int _accountIndex;
+ ///
+ /// Text that prompts the user if they want to add search inputs.
+ ///
+ [ObservableProperty]
+ private string _askToChangeLabel;
+
+ ///
+ /// If the extension allows users to further filter repo results.
+ ///
+ [ObservableProperty]
+ private bool _shouldShowGranularSearch;
+
+ ///
+ /// Controls if the hyperlink button that allows switching to the search terms page is visible.
+ ///
+ [ObservableProperty]
+ private bool _shouldShowChangeSearchTermsHyperlinkButton;
+
///
/// Switches the repos shown to the account selected.
///
[RelayCommand]
private void MenuItemClick(string selectedItemName)
{
- _host.GetService().DispatcherQueue.TryEnqueue(async () =>
+ _dispatcherQueue.TryEnqueue(async () =>
{
SelectedAccount = selectedItemName;
await GetRepositoriesAsync(_selectedRepoProvider, SelectedAccount);
@@ -420,6 +461,20 @@ private void MenuItemClick(string selectedItemName)
});
}
+ ///
+ /// Uses search inputs to search for repos.
+ ///
+ private void SearchRepos()
+ {
+ _dispatcherQueue.TryEnqueue(async () =>
+ {
+ await SearchForRepos(_selectedRepoProvider, SelectedAccount);
+
+ var sdkDisplayName = _providers.GetSDKProvider(_selectedRepoProvider).DisplayName;
+ _addRepoDialog.SelectRepositories(SetRepositories(sdkDisplayName, SelectedAccount));
+ });
+ }
+
[RelayCommand]
private async Task OpenFolderPicker()
{
@@ -428,33 +483,32 @@ private async Task OpenFolderPicker()
}
///
- /// Makes the MenuFlyout object used to display multple accounts in the repo tool.
+ /// If granular search is enabled, this method handles the "SelectionChanged" event on the
+ /// combo box.
///
- /// The MenuFlyout to display.
- ///
- /// The layout is a list of added accounts. A line seperator. One menu item to add an account.
- ///
- private MenuFlyout ConstructFlyout()
+ /// The selection option the user chose.
+ [RelayCommand]
+ private void SelectionOptionsChanged(string selectedItem)
{
- AccountsToShow = new MenuFlyout();
- var newMenu = new MenuFlyout();
- foreach (var account in Accounts)
+ if (selectedItem == null)
{
- var accountMenuItem = new MenuFlyoutItem();
- accountMenuItem.Name = account;
- accountMenuItem.Text = account;
- accountMenuItem.Command = MenuItemClickCommand;
- accountMenuItem.CommandParameter = accountMenuItem.Text;
- newMenu.Items.Add(accountMenuItem);
+ return;
}
- newMenu.Items.Add(new MenuFlyoutSeparator());
- var addAccountMenuItem = new MenuFlyoutItem();
- addAccountMenuItem.Text = _stringResource.GetLocalized("RepoToolAddAnotherAccount");
- addAccountMenuItem.Command = AddAccountClickedCommand;
- newMenu.Items.Add(addAccountMenuItem);
+ List reposWithPathPart = new();
+ foreach (var repo in _allRepositories)
+ {
+ var pathParts = repo.OwningAccountName.Split(Path.DirectorySeparatorChar);
+ var partToCompareAgainst = pathParts[pathParts.Length - 1];
+#pragma warning disable CA1309 // Use ordinal string comparison
+ if (selectedItem.Equals(partToCompareAgainst))
+ {
+ reposWithPathPart.Add(repo);
+ }
+#pragma warning restore CA1309 // Use ordinal string comparison
+ }
- return newMenu;
+ RepositoriesToDisplay = new ObservableCollection(reposWithPathPart);
}
///
@@ -513,6 +567,61 @@ private async Task AddAccountClicked()
}
}
+ ///
+ /// Filters all repos down to any that start with text.
+ /// A side-effect of filtering is that SelectionChanged fires for every selected repo but only on removal.
+ /// SelectionChanged isn't fired for re-adding because repos are removed, not added. To prevent the RepoTool from forgetting the repos that were selected
+ /// the flag _isFiltering is used to prevent modifications to EverythingToClone.
+ /// Once filtering is done SelectRange is called on each item in EverythingToClone to re-select them.
+ ///
+ /// The text to use with .Contains
+ public void FilterRepositories(string text)
+ {
+ IEnumerable filteredRepositories;
+ if (text.Equals(string.Empty, StringComparison.OrdinalIgnoreCase))
+ {
+ filteredRepositories = _allRepositories;
+ }
+ else
+ {
+ filteredRepositories = _allRepositories
+ .Where(x => x.RepoDisplayName.Contains(text, StringComparison.OrdinalIgnoreCase));
+ }
+
+ _isFiltering = true;
+ RepositoriesToDisplay = new ObservableCollection(filteredRepositories);
+ _isFiltering = false;
+ }
+
+ ///
+ /// Makes the MenuFlyout object used to display multple accounts in the repo tool.
+ ///
+ /// The MenuFlyout to display.
+ ///
+ /// The layout is a list of added accounts. A line seperator. One menu item to add an account.
+ ///
+ private MenuFlyout ConstructFlyout()
+ {
+ var newMenu = new MenuFlyout();
+ foreach (var account in Accounts)
+ {
+ var accountMenuItem = new MenuFlyoutItem();
+ accountMenuItem.Name = account;
+ accountMenuItem.Text = account;
+ accountMenuItem.Command = MenuItemClickCommand;
+ accountMenuItem.CommandParameter = accountMenuItem.Text;
+ newMenu.Items.Add(accountMenuItem);
+ }
+
+ newMenu.Items.Add(new MenuFlyoutSeparator());
+ var addAccountMenuItem = new MenuFlyoutItem();
+ addAccountMenuItem.Text = _stringResource.GetLocalized("RepoToolAddAnotherAccount");
+ addAccountMenuItem.Command = AddAccountClickedCommand;
+ newMenu.Items.Add(addAccountMenuItem);
+
+ return newMenu;
+ }
+
public AddRepoViewModel(
SetupFlowOrchestrator setupFlowOrchestrator,
ISetupFlowStringResource stringResource,
@@ -525,6 +634,7 @@ public AddRepoViewModel(
_addRepoDialog = addRepoDialog;
_stringResource = stringResource;
_host = host;
+ _dispatcherQueue = host.GetService().DispatcherQueue;
_loginUiContent = new Frame();
_setupFlowOrchestrator = setupFlowOrchestrator;
@@ -674,18 +784,77 @@ public async Task ChangeToRepoPageAsync()
EditDevDriveViewModel.ShowDevDriveUIIfEnabled();
SelectedAccount = Accounts.First();
ShouldEnablePrimaryButton = false;
+ MenuItemClick((AccountsToShow.Items[0] as MenuFlyoutItem).Text);
}
Log.Logger?.ReportInfo(Log.Component.RepoConfig, "Changing to Repo page");
ShowUrlPage = false;
ShowAccountPage = false;
ShowRepoPage = true;
+
+ ShouldShowSelectingSearchTerms = false;
+ ShouldShowGranularSearch = false;
+ ShouldShowChangeSearchTermsHyperlinkButton = _providers.IsSearchingEnabled(_selectedRepoProvider);
+ AskToChangeLabel = _providers.GetAskChangeSearchFieldsLabel(_selectedRepoProvider);
+
CurrentPage = PageKind.Repositories;
PrimaryButtonText = _stringResource.GetLocalized(StringResourceKey.RepoEverythingElsePrimaryButtonText);
ShouldShowLoginUi = false;
// The only way to get the repo page is through the account page.
- // No need to change toggle buttons.
+ // No need to toggle the clone button.
+ }
+
+ ///
+ /// Sends out a request to search for repos using searchInputs.
+ ///
+ /// The values to search for repos with.
+ public void SearchForRepos(Dictionary searchInputs)
+ {
+ _repoSearchInputs = searchInputs;
+ SearchRepos();
+ }
+
+ public void ChangeToSelectSearchTermsPage()
+ {
+ CurrentPage = PageKind.SearchFields;
+ IsFetchingRepos = false;
+ Log.Logger?.ReportInfo(Log.Component.RepoConfig, "Changing to select search terms page");
+ ShowUrlPage = false;
+ ShowAccountPage = false;
+ ShowRepoPage = false;
+ ShouldShowSelectingSearchTerms = true;
+ FolderPickerViewModel.ShouldShowFolderPicker = false;
+ EditDevDriveViewModel.ShowDevDriveInformation = false;
+ PrimaryButtonText = "Connect";
+ ShouldEnablePrimaryButton = true;
+ }
+
+ ///
+ /// Asks the provider for search terms for querying repositories.
+ ///
+ /// The provider to ask
+ /// The names of the search fields.
+ public List GetSearchTerms()
+ {
+ return _providers.GetSearchTerms(_selectedRepoProvider);
+ }
+
+ ///
+ /// Asks the provider for a list of suggestions, given values of other search terms.
+ ///
+ /// The account of the user
+ /// All information found in the search grid
+ /// The field to request data for
+ ///
+ /// uses _selectedRepoProvider.
+ ///
+ /// A list of names that can be used for the field.
+ public List GetSuggestionsFor(string loginId, Dictionary inputFields, string fieldName)
+ {
+ var loggedInDeveloper = _providers.GetAllLoggedInAccounts(_selectedRepoProvider).FirstOrDefault(x => x.LoginId == loginId);
+
+ return _providers.GetValuesFor(_selectedRepoProvider, loggedInDeveloper, inputFields, fieldName);
}
///
@@ -723,7 +892,13 @@ public bool ValidateRepoInformation()
}
else if (CurrentPage == PageKind.AddViaAccount || CurrentPage == PageKind.Repositories)
{
- return EverythingToClone.Count > 0;
+ return EverythingToClone.Count > 0;
+ }
+ else if (CurrentPage == PageKind.SearchFields)
+ {
+ // IRepositoryProvider2 does not impose a structure to the search terms.
+ // Any combination of search terms, including empty, is accepted.
+ return true;
}
else
{
@@ -778,14 +953,6 @@ public async Task GetAccountsAsync(string repositoryProviderName, Frame loginFra
// To avoid this, just store the login id.
Accounts = new ObservableCollection(loggedInAccounts.Select(x => x.LoginId));
AccountsToShow = ConstructFlyout();
-
- // The dialog makes a user log in if they have no accounts.
- // keep this here just in case.
- if (Accounts.Any())
- {
- SelectedAccount = Accounts.First();
- MenuItemClick((AccountsToShow.Items[0] as MenuFlyoutItem).Text);
- }
}
///
@@ -1073,27 +1240,131 @@ private void InitiateAddAccountUserExperienceAsync(RepositoryProvider provider,
}
}
+ ///
+ /// Starts the task to search for repos.
+ ///
+ /// The name of the selected repository Provider.
+ /// The loginId of the user.
+ /// An awaitable task.
+ private Task StartSearchingForRepos(string repositoryProvider, string loginId)
+ {
+ return Task.Run(
+ () =>
+ {
+ TelemetryFactory.Get().Log("RepoTool_GetRepos_Event", LogLevel.Critical, new RepoToolEvent("GettingAllLoggedInAccounts"), _activityId);
+ var loggedInDeveloper = _providers.GetAllLoggedInAccounts(repositoryProvider).FirstOrDefault(x => x.LoginId == loginId);
+
+ TelemetryFactory.Get().Log("RepoTool_GetRepos_Event", LogLevel.Critical, new RepoToolEvent("GettingAllRepos"), _activityId);
+ return _providers.SearchForRepos(repositoryProvider, loggedInDeveloper, _repoSearchInputs);
+ });
+ }
+
+ ///
+ /// Starts the task to get all repos.
+ ///
+ /// The name of the selected repository Provider.
+ /// The loginId of the user.
+ /// An awaitable task.
+ private Task StartGettingAllRepos(string repositoryProvider, string loginId)
+ {
+ return Task.Run(
+ () =>
+ {
+ TelemetryFactory.Get().Log("RepoTool_GetRepos_Event", LogLevel.Critical, new RepoToolEvent("GettingAllLoggedInAccounts"), _activityId);
+ var loggedInDeveloper = _providers.GetAllLoggedInAccounts(repositoryProvider).FirstOrDefault(x => x.LoginId == loginId);
+
+ TelemetryFactory.Get().Log("RepoTool_GetRepos_Event", LogLevel.Critical, new RepoToolEvent("GettingAllRepos"), _activityId);
+ return _providers.GetAllRepositories(repositoryProvider, loggedInDeveloper);
+ });
+ }
+
+ ///
+ /// Takes a task of getting repositories and makes sure only the most recent request is used.
+ ///
+ /// The loginId of the user
+ /// The running task that is getting repos.
+ /// An awaitable task.
+ private async Task CoordinateTasks(string loginId, Task runningTask)
+ {
+ _dispatcherQueue.TryEnqueue(() =>
+ {
+ SelectedAccount = loginId;
+ IsFetchingRepos = true;
+ });
+
+ // Multiple calls can execute at the same time. DevHome uses the results of the
+ // most recent query. A list of tasks is used to keep track of all running queries.
+ // When a query is done, it is compared with the id of the most recently executed task.
+ // if a match, DevHome uses that.
+ // Using locks here to control access to non-thread safe collections.
+ lock (_setRepositoriesLock)
+ {
+ _taskToUseForResults = runningTask;
+ _runningGetReposTasks.Add(runningTask);
+ }
+
+ await runningTask;
+ RepositorySearchInformation repoSearchInformation;
+ lock (_setRepositoriesLock)
+ {
+ _runningGetReposTasks.Remove(runningTask);
+ if (runningTask.Id != _taskToUseForResults.Id)
+ {
+ _repositoriesForAccount ??= new List();
+ return;
+ }
+
+ repoSearchInformation = runningTask.Result;
+ _repositoriesForAccount = repoSearchInformation.Repositories;
+ try
+ {
+ _allRepositories = repoSearchInformation.Repositories.Select(x => new RepoViewListItem(x)).ToList();
+ }
+ catch (Exception ex)
+ {
+ GlobalLog.Logger?.ReportError($"Exception thrown while selecting repositories from the return object", ex);
+ _allRepositories = new();
+ }
+ }
+
+ // Update the UI.
+ _dispatcherQueue.TryEnqueue(() =>
+ {
+ ShouldShowGranularSearch = DoesTheExtensionUseGranularSearch(repoSearchInformation);
+ SelectionOptionsPrefix = repoSearchInformation.SelectionOptionsLabel;
+ SelectionOptions = new ObservableCollection(repoSearchInformation.SelectionOptions);
+ SelectionOptionsPlaceholderText = repoSearchInformation.SelectionOptionsPlaceHolderText;
+
+ IsFetchingRepos = false;
+ });
+ }
+
+ private bool DoesTheExtensionUseGranularSearch(RepositorySearchInformation repoSearchInformation)
+ {
+ return !string.IsNullOrEmpty(repoSearchInformation.SelectionOptionsLabel) &&
+ !string.IsNullOrEmpty(repoSearchInformation.SelectionOptionsPlaceHolderText) &&
+ repoSearchInformation.SelectionOptions.Count != 0;
+ }
+
+ public async Task SearchForRepos(string repositoryProvider, string loginId)
+ {
+ var localTask = StartSearchingForRepos(repositoryProvider, loginId);
+ await CoordinateTasks(loginId, localTask);
+ }
+
///
/// Gets all the repositories for the specified provider and account.
///
///
/// The side effect of this method is _repositoriesForAccount is populated with repositories.
+ /// If _isSearchingEnabled is true, the path string, and combobox will be populated with values.
///
/// The provider. This should match the display name of the extension
/// The login Id to get the repositories for
public async Task GetRepositoriesAsync(string repositoryProvider, string loginId)
{
- SelectedAccount = loginId;
- IsFetchingRepos = true;
- await Task.Run(() =>
- {
- TelemetryFactory.Get().Log("RepoTool_GetRepos_Event", LogLevel.Critical, new RepoToolEvent("GettingAllLoggedInAccounts"), _activityId);
- var loggedInDeveloper = _providers.GetAllLoggedInAccounts(repositoryProvider).FirstOrDefault(x => x.LoginId == loginId);
-
- TelemetryFactory.Get().Log("RepoTool_GetRepos_Event", LogLevel.Critical, new RepoToolEvent("GettingAllRepos"), _activityId);
- _repositoriesForAccount = _providers.GetAllRepositories(repositoryProvider, loggedInDeveloper);
- });
- IsFetchingRepos = false;
+ var localTask = StartGettingAllRepos(repositoryProvider, loginId);
+ await CoordinateTasks(loginId, localTask);
}
///
@@ -1104,7 +1375,7 @@ await Task.Run(() =>
/// All previously selected repos excluding any added via URL.
public IEnumerable SetRepositories(string repositoryProvider, string loginId)
{
- Repositories = new ObservableCollection(OrderRepos(_repositoriesForAccount));
+ RepositoriesToDisplay = new ObservableCollection(_repositoriesForAccount.Select(x => new RepoViewListItem(x)));
return _previouslySelectedRepos.Where(x => x.OwningAccount != null)
.Where(x => x.ProviderName.Equals(repositoryProvider, StringComparison.OrdinalIgnoreCase)
@@ -1121,7 +1392,7 @@ public void SetCloneLocation(string cloneLocation)
Log.Logger?.ReportInfo(Log.Component.RepoConfig, $"Setting the clone location for all repositories to {cloneLocation}");
foreach (var cloningInformation in EverythingToClone)
{
- // N^2 algorithm. Shouldn't be too slow unless at least 100 repos are added.
+ // N^2 algorithm. Should change to something else when the number of repos is large.
if (!_previouslySelectedRepos.Any(x => x == cloningInformation))
{
cloningInformation.CloningLocation = new DirectoryInfo(cloneLocation);
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/FolderPickerViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/FolderPickerViewModel.cs
index b7a46dba7e..ff8637000f 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/FolderPickerViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/FolderPickerViewModel.cs
@@ -27,7 +27,7 @@ public partial class FolderPickerViewModel : ObservableObject
/// Some pages don't show a folder picker.
///
[ObservableProperty]
- private Visibility _shouldShowFolderPicker;
+ private bool _shouldShowFolderPicker;
///
/// The clone location the repos should be cloned to.
@@ -68,7 +68,8 @@ public partial class FolderPickerViewModel : ObservableObject
public FolderPickerViewModel(ISetupFlowStringResource stringResource, SetupFlowOrchestrator setupFlowOrchestrator)
{
_stringResource = stringResource;
- ShouldShowFolderPicker = Visibility.Visible;
+ ShouldShowFolderPicker = true;
+ CloneLocation = string.Empty;
IsBrowseButtonEnabled = true;
_setupFlowOrchestrator = setupFlowOrchestrator;
SetDefaultCloneLocation();
@@ -77,13 +78,13 @@ public FolderPickerViewModel(ISetupFlowStringResource stringResource, SetupFlowO
public void ShowFolderPicker()
{
Log.Logger?.ReportInfo(Log.Component.RepoConfig, "Showing folder picker");
- ShouldShowFolderPicker = Visibility.Visible;
+ ShouldShowFolderPicker = true;
}
public void CloseFolderPicker()
{
Log.Logger?.ReportInfo(Log.Component.RepoConfig, "Closing folder picker");
- ShouldShowFolderPicker = Visibility.Collapsed;
+ ShouldShowFolderPicker = false;
}
public void EnableBrowseButton()
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml
index ed090e9a01..723d2b74a8 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml
@@ -26,6 +26,7 @@
+
@@ -103,24 +104,63 @@
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
-
-
-
-
+
@@ -143,7 +183,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml.cs
index 390cb965a1..d0076e2d82 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/AddRepoDialog.xaml.cs
@@ -32,6 +32,8 @@ public partial class AddRepoDialog : ContentDialog
private readonly List _previouslySelectedRepos = new();
+ private readonly Dictionary> _searchFieldsAndValues;
+
///
/// Gets or sets the view model to handle selecting and de-selecting repositories.
///
@@ -67,6 +69,7 @@ public AddRepoDialog(
AddViaUrlSegmentedItem.IsSelected = true;
SwitchViewsSegmentedView.SelectedIndex = 1;
_host = host;
+ _searchFieldsAndValues = new();
}
///
@@ -139,7 +142,7 @@ private void CloneLocation_TextChanged(object sender, TextChangedEventArgs e)
public void SelectRepositories(IEnumerable reposToSelect)
{
AddRepoViewModel.IsCallingSelectRange = true;
- var onlyRepoNames = AddRepoViewModel.Repositories.Select(x => x.RepoName).ToList();
+ var onlyRepoNames = AddRepoViewModel.RepositoriesToDisplay.Select(x => x.RepoName).ToList();
foreach (var repoToSelect in reposToSelect)
{
var index = onlyRepoNames.IndexOf(repoToSelect.RepoName);
@@ -259,6 +262,24 @@ private async void AddRepoContentDialog_PrimaryButtonClick(ContentDialog sender,
deferral.Complete();
}
}
+ else if (AddRepoViewModel.CurrentPage == PageKind.SearchFields)
+ {
+ args.Cancel = true;
+ Dictionary searchInput = new();
+ foreach (var searchBox in ShowingSearchTermsGrid.Children)
+ {
+ if (searchBox is AutoSuggestBox suggestBox)
+ {
+ searchInput.Add(suggestBox.Header as string, suggestBox.Text);
+ }
+ }
+
+ // switching to the repo page causes repos to be queried.
+ var deferral = args.GetDeferral();
+ await AddRepoViewModel.ChangeToRepoPageAsync();
+ AddRepoViewModel.SearchForRepos(searchInput);
+ deferral.Complete();
+ }
}
///
@@ -334,4 +355,46 @@ public void UpdateDevDriveInfo()
AddRepoViewModel.FolderPickerViewModel.InDevDriveScenario = true;
AddRepoViewModel.EditDevDriveViewModel.IsDevDriveCheckboxChecked = true;
}
+
+ private void FilterSuggestions(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
+ {
+ sender.ItemsSource = _searchFieldsAndValues[sender.Header.ToString()].Where(x => x.Contains(sender.Text));
+ return;
+ }
+
+ private async void SwitchToSearchPage(object sender, RoutedEventArgs e)
+ {
+ AddRepoViewModel.ChangeToSelectSearchTermsPage();
+ _searchFieldsAndValues.Clear();
+ ShowingSearchTermsGrid.Children.Clear();
+ GatheringSearchValuesGrid.Visibility = Visibility.Visible;
+ ShowingSearchTermsGrid.Visibility = Visibility.Collapsed;
+
+ var loginId = (string)AddRepoViewModel.SelectedAccount;
+ var searchTerms = AddRepoViewModel.GetSearchTerms();
+ ShowingSearchTermsGrid.RowSpacing = 10;
+
+ // Set up the UI for searching.
+ var searchTermRow = 0;
+ for (var termIndex = 0; termIndex < searchTerms.Count; termIndex++)
+ {
+ var localTermIndex = termIndex;
+ ShowingSearchTermsGrid.RowDefinitions.Add(new RowDefinition());
+
+ var searchFieldName = string.Empty;
+ var searchFieldSuggestions = await Task.Run(() => AddRepoViewModel.GetSuggestionsFor(loginId, new(), searchTerms[localTermIndex]));
+
+ _searchFieldsAndValues.Add(searchTerms[localTermIndex], searchFieldSuggestions);
+ var suggestBox = new AutoSuggestBox();
+ suggestBox.Header = searchTerms[localTermIndex];
+ suggestBox.ItemsSource = searchFieldSuggestions;
+ suggestBox.Text = searchFieldName;
+ suggestBox.TextChanged += FilterSuggestions;
+ ShowingSearchTermsGrid.Children.Add(suggestBox);
+ Grid.SetRow(suggestBox, searchTermRow++);
+ }
+
+ GatheringSearchValuesGrid.Visibility = Visibility.Collapsed;
+ ShowingSearchTermsGrid.Visibility = Visibility.Visible;
+ }
}
From c1cdcc735aa3a91b24465e5bf2ba66866554ce3f Mon Sep 17 00:00:00 2001
From: Kristen Schau <47155823+krschau@users.noreply.github.com>
Date: Fri, 22 Mar 2024 12:42:29 -0400
Subject: [PATCH 019/121] Remove unused Usings (#2375)
* remove unused usings
* reorder
* remove one that got added
---
.../src/DevSetupAgent/DevAgentService.cs | 3 ---
.../src/DevSetupAgent/HostRegistryChannel.cs | 4 ----
.../src/DevSetupAgent/IHostExtensions.cs | 4 ----
.../src/DevSetupAgent/IRequestManager.cs | 2 --
HyperVExtension/src/DevSetupAgent/Program.cs | 1 -
.../src/DevSetupAgent/RegistryWatcher.cs | 6 ------
.../src/DevSetupAgent/RequestManager.cs | 2 --
.../src/DevSetupAgent/Requests/AckRequest.cs | 2 --
.../src/DevSetupAgent/Requests/ConfigureRequest.cs | 1 -
.../DevSetupAgent/Requests/ErrorNoTypeRequest.cs | 2 --
.../src/DevSetupAgent/Requests/ErrorRequest.cs | 2 --
.../Requests/ErrorUnsupportedRequest.cs | 2 --
.../DevSetupAgent/Requests/GetVersionRequest.cs | 2 --
.../Requests/IsUserLoggedInRequest.cs | 2 --
.../DevSetupAgent/Requests/NtStatusException.cs | 2 --
.../DevSetupAgent/Responses/ConfigureResponse.cs | 1 -
.../Responses/TooManyRequestsResponse.cs | 2 --
.../DevSetupEngine/DevSetupEngineClassFactory.cs | 3 ---
.../src/DevSetupEngine/IHostExtensions.cs | 1 -
.../OpenConfigurationSetException.cs | 1 -
.../ApplyConfigurationResult.cs | 7 -------
.../Extensions/StringExtensions.cs | 4 ----
.../Providers/MessageHelper.cs | 4 ----
.../ApplyConfigurationOperation.cs | 9 ---------
.../CommunicationWithGuest/GuestKvpChannel.cs | 7 -------
.../CommunicationWithGuest/GuestKvpSession.cs | 11 -----------
.../Responses/ErrorResponse.cs | 3 ---
.../Responses/ResponseFactory.cs | 1 -
.../CommunicationWithGuest/WmiUtility.cs | 3 ---
.../Exceptions/ComputeSystemOperationException.cs | 1 -
.../Exceptions/HyperVAdminGroupException.cs | 6 ------
.../Exceptions/HyperVManagerException.cs | 6 ------
.../Exceptions/HyperVModuleNotLoadedException.cs | 6 ------
.../Helpers/AdaptiveCardActionPayload.cs | 2 --
.../src/HyperVExtension/Helpers/Json.cs | 2 --
.../HyperVExtension/Models/HyperVVirtualMachine.cs | 2 --
.../HyperVExtension/Models/PowerShellSession.cs | 3 ---
.../Models/WaitForLoginAdaptiveCardSession.cs | 2 --
.../Models/WindowsIdentityService.cs | 6 ------
.../Models/WindowsServiceController.cs | 1 -
.../HyperVExtension/Providers/HyperVProvider.cs | 1 -
.../src/HyperVExtension/Services/HyperVManager.cs | 3 ---
.../HyperVExtension/Services/PowerShellService.cs | 3 ---
.../src/HyperVExtensionServer/Program.cs | 4 ----
.../src/Logging/listeners/ListenerBase.cs | 2 --
HyperVExtension/src/Telemetry/ILogger.cs | 4 ----
HyperVExtension/src/Telemetry/LogLevel.cs | 6 ------
HyperVExtension/src/Telemetry/Logger.cs | 5 -----
HyperVExtension/src/Telemetry/LoggerFactory.cs | 6 ------
.../DevSetupAgentIntegrationTest.cs | 1 -
.../DevSetupEngineIntegrationTest.cs | 2 --
.../test/DevSetupEngine.Test/IHostExtensions.cs | 1 -
.../Services/HyperVExtensionIntegrationTest.cs | 2 --
.../Services/HyperVManagerTest.cs | 1 -
.../Services/HyperVVirtualMachineTest.cs | 4 ----
.../HyperVExtension/Mocks/PSCustomObjectMock.cs | 2 --
.../Mocks/WindowsIdentityServiceMock.cs | 1 -
HyperVExtension/test/HyperVExtension/Usings.cs | 1 -
common/Contracts/IComputeSystemService.cs | 4 ----
common/Contracts/IWindowsIdentityService.cs | 6 ------
.../Environments/CustomControls/CardBody.xaml.cs | 1 -
.../Environments/Helpers/ComputeSystemHelpers.cs | 2 --
.../Environments/Helpers/StringResourceHelper.cs | 4 ----
common/Environments/Models/CardProperty.cs | 3 ---
common/Environments/Models/ComputeSystem.cs | 2 --
.../Environments/Models/ComputeSystemProvider.cs | 6 ------
.../Models/ComputeSystemProviderDetails.cs | 5 -----
.../Models/ComputeSystemsLoadedData.cs | 1 -
.../Environments/Services/ComputeSystemManager.cs | 2 --
.../Environments/Services/IComputeSystemManager.cs | 2 --
common/Helpers/EnumHelper.cs | 4 ----
common/Models/ProviderOperationResultWrapper.cs | 4 ----
common/Services/ComputeSystemService.cs | 2 --
common/Services/LocalSettingsService.cs | 1 -
common/Services/ToastNotificationService.cs | 7 -------
common/Services/WindowsIdentityService.cs | 4 ----
logging/listeners/ListenerBase.cs | 2 --
.../ViewModels/ExperimentalFeaturesViewModel.cs | 1 -
src/MainWindow.xaml.cs | 1 -
src/Services/ExtensionService.cs | 1 -
src/Services/ProtocolActivationHandler.cs | 5 -----
src/ViewModels/InfoBarModel.cs | 6 ------
src/Views/ShellPage.xaml.cs | 1 -
telemetry/DevHome.Telemetry/LogLevel.cs | 6 ------
test/GitWatcherTests.cs | 1 -
test/TestClass.cs | 2 --
.../Controls/SelectableMenuFlyoutItem.cs | 1 -
.../CustomControls/CardFlyout.xaml.cs | 1 -
.../Extensions/ServiceExtensions.cs | 1 -
.../DevHome.Environments/Helpers/DataExtractor.cs | 10 ----------
.../Helpers/EnvironmentsExtensionsService.cs | 6 ------
.../DevHome.Environments/TestModels/EmptyDevId.cs | 5 -----
.../TestModels/TestExtensionWrapper.cs | 2 --
.../DevHome.Environments/TestModels/TestSystems.cs | 2 --
.../ViewModels/ComputeSystemViewModel.cs | 3 ---
.../ViewModels/LandingPageViewModel.cs | 6 ------
.../ViewModels/OperationsViewModel.cs | 2 --
.../DevHome.Environments/Views/LandingPage.xaml.cs | 9 ---------
.../src/ViewModels/TestExperimentViewModel.cs | 6 ------
.../src/Views/TestExperimentPage.xaml.cs | 14 --------------
.../ViewModels/InstalledPackageViewModel.cs | 1 -
tools/SampleTool/src/Class1.cs | 6 ------
tools/SampleTool/unittest/TestClass.cs | 2 --
.../Helpers/ElevatedConfigureUnitTaskResult.cs | 2 --
.../Tasks/ElevatedInstallTask.cs | 1 -
.../AddRepoDialogTests.cs | 1 -
.../DevDriveEnumToLocalizedStringConverterTest.cs | 2 --
.../LoadingScreenTests.cs | 1 -
.../SDKApplyConfigurationSetResultException.cs | 4 ----
.../SDKOpenConfigurationSetResultException.cs | 4 ----
.../Extensions/ServiceExtensions.cs | 2 --
.../Models/ActionCenterMessages.cs | 1 -
.../DevHome.SetupFlow/Models/CloneRepoTask.cs | 1 -
.../Models/ConfigurationUnitResult.cs | 1 -
.../Models/ConfigureTargetTask.cs | 7 -------
.../DevHome.SetupFlow/Models/ConfigureTask.cs | 1 -
.../DevHome.SetupFlow/Models/CreateDevDriveTask.cs | 1 -
.../DevHome.SetupFlow/Models/ISetupTask.cs | 4 ----
.../DevHome.SetupFlow/Models/IWinGetPackage.cs | 1 -
.../DevHome.SetupFlow/Models/InstallPackageTask.cs | 1 -
.../Models/RepositoryProviders.cs | 1 -
.../DevHome.SetupFlow/Models/TaskInformation.cs | 3 ---
.../Models/WingetConfigure/GitDscSettings.cs | 2 --
.../WingetConfigure/SDKApplyConfigurationResult.cs | 1 -
.../SDKApplyConfigurationSetResult.cs | 3 ---
.../SDKConfigurationSetChangeWrapper.cs | 4 ----
.../WingetConfigure/SDKConfigurationUnitWrapper.cs | 4 ----
.../SDKOpenConfigurationSetResult.cs | 5 -----
.../WingetConfigure/WinGetConfigAssertion.cs | 2 --
.../Models/WingetConfigure/WinGetConfigFile.cs | 7 -------
.../WingetConfigure/WinGetConfigProperties.cs | 2 --
.../Models/WingetConfigure/WinGetConfigResource.cs | 2 --
.../WingetConfigure/WinGetConfigSettingsBase.cs | 2 --
.../Models/WingetConfigure/WinGetDscSettings.cs | 2 --
.../WingetConfigure/WingGetConfigDirectives.cs | 2 --
.../ComputeSystemsListViewModelSelector.cs | 1 -
.../Services/ComputeSystemViewModelFactory.cs | 1 -
.../Services/ConfigurationFileBuilder.cs | 1 -
.../Services/IWindowsPackageManager.cs | 1 -
.../Services/SetupFlowOrchestrator.cs | 1 -
.../WinGet/Operations/WinGetGetPackageOperation.cs | 1 -
.../Services/WinGetPackageDataSource.cs | 1 -
.../TaskGroups/DevDriveTaskGroup.cs | 1 -
.../TaskGroups/RepoConfigTaskGroup.cs | 1 -
.../TaskGroups/SetupTargetTaskGroup.cs | 9 ---------
.../Environments/ComputeSystemsListViewModel.cs | 2 --
.../ViewModels/LoadingMessageViewModel.cs | 3 ---
.../ViewModels/LoadingViewModel.cs | 9 ---------
.../ViewModels/ReviewViewModel.cs | 4 ----
.../ViewModels/SetupFlowViewModel.cs | 1 -
.../ViewModels/SetupTargetReviewViewModel.cs | 4 ----
.../ViewModels/SetupTargetViewModel.cs | 6 ------
.../Views/EditClonePathDialog.xaml.cs | 1 -
.../DevHome.SetupFlow/Views/PackageView.xaml.cs | 2 --
.../Views/SetupTargetReviewView.xaml.cs | 4 ----
155 files changed, 474 deletions(-)
diff --git a/HyperVExtension/src/DevSetupAgent/DevAgentService.cs b/HyperVExtension/src/DevSetupAgent/DevAgentService.cs
index 20ac557ef7..51dec601bf 100644
--- a/HyperVExtension/src/DevSetupAgent/DevAgentService.cs
+++ b/HyperVExtension/src/DevSetupAgent/DevAgentService.cs
@@ -1,9 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using HyperVExtension.Telemetry;
-using Microsoft.Windows.AppLifecycle;
-
namespace HyperVExtension.DevSetupAgent;
///
diff --git a/HyperVExtension/src/DevSetupAgent/HostRegistryChannel.cs b/HyperVExtension/src/DevSetupAgent/HostRegistryChannel.cs
index af77073108..334002d92c 100644
--- a/HyperVExtension/src/DevSetupAgent/HostRegistryChannel.cs
+++ b/HyperVExtension/src/DevSetupAgent/HostRegistryChannel.cs
@@ -1,14 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Diagnostics.PerformanceData;
using System.Runtime.InteropServices;
using System.Text;
-using DevHome.Logging;
using HyperVExtension.HostGuestCommunication;
-using Microsoft.UI.Xaml.Controls;
using Microsoft.Win32;
-using Windows.Foundation.Collections;
namespace HyperVExtension.DevSetupAgent;
diff --git a/HyperVExtension/src/DevSetupAgent/IHostExtensions.cs b/HyperVExtension/src/DevSetupAgent/IHostExtensions.cs
index 110dad9458..4112f55721 100644
--- a/HyperVExtension/src/DevSetupAgent/IHostExtensions.cs
+++ b/HyperVExtension/src/DevSetupAgent/IHostExtensions.cs
@@ -1,10 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-
namespace HyperVExtension.DevSetupAgent;
public static class IHostExtensions
diff --git a/HyperVExtension/src/DevSetupAgent/IRequestManager.cs b/HyperVExtension/src/DevSetupAgent/IRequestManager.cs
index 03eeec1438..4ec8f44562 100644
--- a/HyperVExtension/src/DevSetupAgent/IRequestManager.cs
+++ b/HyperVExtension/src/DevSetupAgent/IRequestManager.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using HyperVExtension.DevSetupAgent;
-
namespace HyperVExtension.DevSetupAgent;
///
diff --git a/HyperVExtension/src/DevSetupAgent/Program.cs b/HyperVExtension/src/DevSetupAgent/Program.cs
index 9bc8c6c5aa..2af76210aa 100644
--- a/HyperVExtension/src/DevSetupAgent/Program.cs
+++ b/HyperVExtension/src/DevSetupAgent/Program.cs
@@ -3,7 +3,6 @@
using System.Runtime.InteropServices;
using HyperVExtension.DevSetupAgent;
-using Microsoft.Windows.DevHome.DevSetupEngine;
using Windows.Win32;
using Windows.Win32.Security;
using Windows.Win32.System.Com;
diff --git a/HyperVExtension/src/DevSetupAgent/RegistryWatcher.cs b/HyperVExtension/src/DevSetupAgent/RegistryWatcher.cs
index 56a3da6e0f..65136a4256 100644
--- a/HyperVExtension/src/DevSetupAgent/RegistryWatcher.cs
+++ b/HyperVExtension/src/DevSetupAgent/RegistryWatcher.cs
@@ -2,14 +2,8 @@
// Licensed under the MIT License.
using System.ComponentModel;
-using System.Reflection;
-using System.Reflection.Emit;
using System.Runtime.InteropServices;
-using DevHome.Logging;
-using Microsoft.Extensions.Logging;
-using Microsoft.VisualBasic;
using Microsoft.Win32;
-using Windows.Devices.Geolocation;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Registry;
diff --git a/HyperVExtension/src/DevSetupAgent/RequestManager.cs b/HyperVExtension/src/DevSetupAgent/RequestManager.cs
index 660c679f92..5a0d3464e8 100644
--- a/HyperVExtension/src/DevSetupAgent/RequestManager.cs
+++ b/HyperVExtension/src/DevSetupAgent/RequestManager.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using static System.Reflection.Metadata.BlobBuilder;
-
namespace HyperVExtension.DevSetupAgent;
///
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/AckRequest.cs b/HyperVExtension/src/DevSetupAgent/Requests/AckRequest.cs
index 07a3210404..c2a086fc1c 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/AckRequest.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/AckRequest.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Text.Json.Nodes;
-
namespace HyperVExtension.DevSetupAgent;
///
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/ConfigureRequest.cs b/HyperVExtension/src/DevSetupAgent/Requests/ConfigureRequest.cs
index 57f27437a4..f8d269618b 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/ConfigureRequest.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/ConfigureRequest.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using System.Runtime.InteropServices;
-using System.Text.Json.Nodes;
using Microsoft.Windows.DevHome.DevSetupEngine;
using Windows.Win32;
using Windows.Win32.System.Com;
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/ErrorNoTypeRequest.cs b/HyperVExtension/src/DevSetupAgent/Requests/ErrorNoTypeRequest.cs
index 10eda12867..05e83a12dc 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/ErrorNoTypeRequest.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/ErrorNoTypeRequest.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Text.Json.Nodes;
-
namespace HyperVExtension.DevSetupAgent;
///
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/ErrorRequest.cs b/HyperVExtension/src/DevSetupAgent/Requests/ErrorRequest.cs
index dfe9ea8d29..fabc9a2052 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/ErrorRequest.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/ErrorRequest.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Text.Json.Nodes;
-
namespace HyperVExtension.DevSetupAgent;
///
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/ErrorUnsupportedRequest.cs b/HyperVExtension/src/DevSetupAgent/Requests/ErrorUnsupportedRequest.cs
index 867f0f5a67..1807b18174 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/ErrorUnsupportedRequest.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/ErrorUnsupportedRequest.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Text.Json.Nodes;
-
namespace HyperVExtension.DevSetupAgent;
///
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/GetVersionRequest.cs b/HyperVExtension/src/DevSetupAgent/Requests/GetVersionRequest.cs
index d7fc304f9c..1b9c255fcf 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/GetVersionRequest.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/GetVersionRequest.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Text.Json.Nodes;
-
namespace HyperVExtension.DevSetupAgent;
///
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/IsUserLoggedInRequest.cs b/HyperVExtension/src/DevSetupAgent/Requests/IsUserLoggedInRequest.cs
index 3419e5ff8e..ebdf82b51c 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/IsUserLoggedInRequest.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/IsUserLoggedInRequest.cs
@@ -1,10 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Diagnostics;
using System.Security.Principal;
-using System.Text.Json.Nodes;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Security.Authentication.Identity;
diff --git a/HyperVExtension/src/DevSetupAgent/Requests/NtStatusException.cs b/HyperVExtension/src/DevSetupAgent/Requests/NtStatusException.cs
index cd6023a192..896889db34 100644
--- a/HyperVExtension/src/DevSetupAgent/Requests/NtStatusException.cs
+++ b/HyperVExtension/src/DevSetupAgent/Requests/NtStatusException.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Runtime.Serialization;
-
namespace HyperVExtension.DevSetupAgent;
internal sealed class NtStatusException : Exception
diff --git a/HyperVExtension/src/DevSetupAgent/Responses/ConfigureResponse.cs b/HyperVExtension/src/DevSetupAgent/Responses/ConfigureResponse.cs
index df029dbcd5..3843f17585 100644
--- a/HyperVExtension/src/DevSetupAgent/Responses/ConfigureResponse.cs
+++ b/HyperVExtension/src/DevSetupAgent/Responses/ConfigureResponse.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using System.Text.Json;
-using System.Text.Json.Nodes;
using HyperVExtension.HostGuestCommunication;
using Microsoft.Windows.DevHome.DevSetupEngine;
diff --git a/HyperVExtension/src/DevSetupAgent/Responses/TooManyRequestsResponse.cs b/HyperVExtension/src/DevSetupAgent/Responses/TooManyRequestsResponse.cs
index 6eaa4a1e1a..eb515d1e68 100644
--- a/HyperVExtension/src/DevSetupAgent/Responses/TooManyRequestsResponse.cs
+++ b/HyperVExtension/src/DevSetupAgent/Responses/TooManyRequestsResponse.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Text.Json;
-
namespace HyperVExtension.DevSetupAgent;
internal sealed class TooManyRequestsResponse : ResponseBase
diff --git a/HyperVExtension/src/DevSetupEngine/DevSetupEngineClassFactory.cs b/HyperVExtension/src/DevSetupEngine/DevSetupEngineClassFactory.cs
index db3c3b5789..a863a917bd 100644
--- a/HyperVExtension/src/DevSetupEngine/DevSetupEngineClassFactory.cs
+++ b/HyperVExtension/src/DevSetupEngine/DevSetupEngineClassFactory.cs
@@ -1,9 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using Windows.Win32.Foundation;
using WinRT;
diff --git a/HyperVExtension/src/DevSetupEngine/IHostExtensions.cs b/HyperVExtension/src/DevSetupEngine/IHostExtensions.cs
index 19240d0398..31e21caf86 100644
--- a/HyperVExtension/src/DevSetupEngine/IHostExtensions.cs
+++ b/HyperVExtension/src/DevSetupEngine/IHostExtensions.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
diff --git a/HyperVExtension/src/DevSetupEngine/OpenConfigurationSetException.cs b/HyperVExtension/src/DevSetupEngine/OpenConfigurationSetException.cs
index 58f4a9bcc5..205090a219 100644
--- a/HyperVExtension/src/DevSetupEngine/OpenConfigurationSetException.cs
+++ b/HyperVExtension/src/DevSetupEngine/OpenConfigurationSetException.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using Microsoft.Management.Configuration;
namespace HyperVExtension.DevSetupEngine;
diff --git a/HyperVExtension/src/HyperVExtension.HostGuestCommunication/ApplyConfigurationResult.cs b/HyperVExtension/src/HyperVExtension.HostGuestCommunication/ApplyConfigurationResult.cs
index 202710635b..f6a43cc0c2 100644
--- a/HyperVExtension/src/HyperVExtension.HostGuestCommunication/ApplyConfigurationResult.cs
+++ b/HyperVExtension/src/HyperVExtension.HostGuestCommunication/ApplyConfigurationResult.cs
@@ -1,13 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Text.Json.Serialization;
-using Windows.Foundation.Collections;
-
namespace HyperVExtension.HostGuestCommunication;
// Helper class to convert from the DevSetupEngine COM types to the .NET types and use them
diff --git a/HyperVExtension/src/HyperVExtension.HostGuestCommunication/Extensions/StringExtensions.cs b/HyperVExtension/src/HyperVExtension.HostGuestCommunication/Extensions/StringExtensions.cs
index eaa76cb633..b6c7dfc3aa 100644
--- a/HyperVExtension/src/HyperVExtension.HostGuestCommunication/Extensions/StringExtensions.cs
+++ b/HyperVExtension/src/HyperVExtension.HostGuestCommunication/Extensions/StringExtensions.cs
@@ -1,10 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.DependencyInjection;
-
namespace HyperVExtension.HostGuestCommunication;
///
diff --git a/HyperVExtension/src/HyperVExtension.HostGuestCommunication/Providers/MessageHelper.cs b/HyperVExtension/src/HyperVExtension.HostGuestCommunication/Providers/MessageHelper.cs
index a552d2e362..ad4179c0ec 100644
--- a/HyperVExtension/src/HyperVExtension.HostGuestCommunication/Providers/MessageHelper.cs
+++ b/HyperVExtension/src/HyperVExtension.HostGuestCommunication/Providers/MessageHelper.cs
@@ -1,11 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Text;
-using Microsoft.Extensions.DependencyInjection;
using Microsoft.Win32;
namespace HyperVExtension.HostGuestCommunication;
diff --git a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/ApplyConfigurationOperation.cs b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/ApplyConfigurationOperation.cs
index ea4260d9fe..08c70efa37 100644
--- a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/ApplyConfigurationOperation.cs
+++ b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/ApplyConfigurationOperation.cs
@@ -1,19 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.ComponentModel;
-using System.Globalization;
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.WindowsRuntime;
-using System.Threading;
-using HyperVExtension.HostGuestCommunication;
using HyperVExtension.Models;
-using HyperVExtension.Providers;
using Microsoft.Windows.DevHome.SDK;
using Windows.Foundation;
using Windows.Foundation.Collections;
-using Windows.Storage;
-using Windows.Storage.Streams;
using Windows.Win32.Foundation;
using SDK = Microsoft.Windows.DevHome.SDK;
diff --git a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/GuestKvpChannel.cs b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/GuestKvpChannel.cs
index 82c9b0d036..e734293c70 100644
--- a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/GuestKvpChannel.cs
+++ b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/GuestKvpChannel.cs
@@ -1,18 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Globalization;
-using System.Linq;
using System.Management;
-using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading;
using System.Xml;
-using System.Xml.Linq;
using System.Xml.XPath;
using HyperVExtension.HostGuestCommunication;
using HyperVExtension.Providers;
-using Microsoft.Win32;
namespace HyperVExtension.CommunicationWithGuest;
diff --git a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/GuestKvpSession.cs b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/GuestKvpSession.cs
index d8c3f50d9b..97114215bb 100644
--- a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/GuestKvpSession.cs
+++ b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/GuestKvpSession.cs
@@ -1,17 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Globalization;
-using System.Linq;
-using System.Management;
-using System.Runtime.InteropServices;
-using System.Threading;
-using System.Xml;
-using System.Xml.Linq;
-using System.Xml.XPath;
-using HyperVExtension.Providers;
-using Microsoft.Win32;
-
namespace HyperVExtension.CommunicationWithGuest;
///
diff --git a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/Responses/ErrorResponse.cs b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/Responses/ErrorResponse.cs
index 11ee5efa28..709c49434b 100644
--- a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/Responses/ErrorResponse.cs
+++ b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/Responses/ErrorResponse.cs
@@ -1,9 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Text.Json.Nodes;
-using HyperVExtension.CommunicationWithGuest;
-
namespace HyperVExtension.CommunicationWithGuest;
///
diff --git a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/Responses/ResponseFactory.cs b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/Responses/ResponseFactory.cs
index af738f080b..793d8e5068 100644
--- a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/Responses/ResponseFactory.cs
+++ b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/Responses/ResponseFactory.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Text.Json;
using System.Text.Json.Nodes;
using HyperVExtension.Providers;
diff --git a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/WmiUtility.cs b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/WmiUtility.cs
index c540f43930..8ce4adfdd5 100644
--- a/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/WmiUtility.cs
+++ b/HyperVExtension/src/HyperVExtension/CommunicationWithGuest/WmiUtility.cs
@@ -1,10 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Globalization;
using System.Management;
-using System.Management.Automation;
-using System.Web.Services.Description;
using HyperVExtension.Providers;
using Windows.Win32.Foundation;
diff --git a/HyperVExtension/src/HyperVExtension/Exceptions/ComputeSystemOperationException.cs b/HyperVExtension/src/HyperVExtension/Exceptions/ComputeSystemOperationException.cs
index c188a50076..c5887a0a5e 100644
--- a/HyperVExtension/src/HyperVExtension/Exceptions/ComputeSystemOperationException.cs
+++ b/HyperVExtension/src/HyperVExtension/Exceptions/ComputeSystemOperationException.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Globalization;
using Microsoft.Windows.DevHome.SDK;
namespace HyperVExtension.Exceptions;
diff --git a/HyperVExtension/src/HyperVExtension/Exceptions/HyperVAdminGroupException.cs b/HyperVExtension/src/HyperVExtension/Exceptions/HyperVAdminGroupException.cs
index 8ee5ed62f5..355f60db70 100644
--- a/HyperVExtension/src/HyperVExtension/Exceptions/HyperVAdminGroupException.cs
+++ b/HyperVExtension/src/HyperVExtension/Exceptions/HyperVAdminGroupException.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace HyperVExtension.Exceptions;
public class HyperVAdminGroupException : HyperVManagerException
diff --git a/HyperVExtension/src/HyperVExtension/Exceptions/HyperVManagerException.cs b/HyperVExtension/src/HyperVExtension/Exceptions/HyperVManagerException.cs
index 59656c8c37..2f708db3e5 100644
--- a/HyperVExtension/src/HyperVExtension/Exceptions/HyperVManagerException.cs
+++ b/HyperVExtension/src/HyperVExtension/Exceptions/HyperVManagerException.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace HyperVExtension.Exceptions;
public class HyperVManagerException : Exception
diff --git a/HyperVExtension/src/HyperVExtension/Exceptions/HyperVModuleNotLoadedException.cs b/HyperVExtension/src/HyperVExtension/Exceptions/HyperVModuleNotLoadedException.cs
index 138e8ec9b7..6b4a9d056d 100644
--- a/HyperVExtension/src/HyperVExtension/Exceptions/HyperVModuleNotLoadedException.cs
+++ b/HyperVExtension/src/HyperVExtension/Exceptions/HyperVModuleNotLoadedException.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace HyperVExtension.Exceptions;
public class HyperVModuleNotLoadedException : HyperVManagerException
diff --git a/HyperVExtension/src/HyperVExtension/Helpers/AdaptiveCardActionPayload.cs b/HyperVExtension/src/HyperVExtension/Helpers/AdaptiveCardActionPayload.cs
index c98caa4f56..3b3d4f1b3c 100644
--- a/HyperVExtension/src/HyperVExtension/Helpers/AdaptiveCardActionPayload.cs
+++ b/HyperVExtension/src/HyperVExtension/Helpers/AdaptiveCardActionPayload.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Globalization;
-
namespace HyperVExtension.Helpers;
internal sealed class AdaptiveCardActionPayload
diff --git a/HyperVExtension/src/HyperVExtension/Helpers/Json.cs b/HyperVExtension/src/HyperVExtension/Helpers/Json.cs
index 1f974435e7..98d0d18402 100644
--- a/HyperVExtension/src/HyperVExtension/Helpers/Json.cs
+++ b/HyperVExtension/src/HyperVExtension/Helpers/Json.cs
@@ -1,11 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.IO;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
-using System.Threading.Tasks;
namespace HyperVExtension.Helpers;
diff --git a/HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs b/HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs
index 8cf3e8310b..c7eed54632 100644
--- a/HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs
+++ b/HyperVExtension/src/HyperVExtension/Models/HyperVVirtualMachine.cs
@@ -1,13 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Data;
using System.Globalization;
using System.Management.Automation;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
-using System.Threading;
using HyperVExtension.Common;
using HyperVExtension.Common.Extensions;
using HyperVExtension.CommunicationWithGuest;
diff --git a/HyperVExtension/src/HyperVExtension/Models/PowerShellSession.cs b/HyperVExtension/src/HyperVExtension/Models/PowerShellSession.cs
index 7a7a201dc5..767b414615 100644
--- a/HyperVExtension/src/HyperVExtension/Models/PowerShellSession.cs
+++ b/HyperVExtension/src/HyperVExtension/Models/PowerShellSession.cs
@@ -1,12 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Management.Automation;
-using System.Text;
-using System.Threading.Tasks;
namespace HyperVExtension.Models;
diff --git a/HyperVExtension/src/HyperVExtension/Models/WaitForLoginAdaptiveCardSession.cs b/HyperVExtension/src/HyperVExtension/Models/WaitForLoginAdaptiveCardSession.cs
index 6f2b5c3032..fb9c7bdc9e 100644
--- a/HyperVExtension/src/HyperVExtension/Models/WaitForLoginAdaptiveCardSession.cs
+++ b/HyperVExtension/src/HyperVExtension/Models/WaitForLoginAdaptiveCardSession.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Net;
-using System.Security;
using HyperVExtension.CommunicationWithGuest;
using HyperVExtension.Helpers;
using HyperVExtension.Providers;
diff --git a/HyperVExtension/src/HyperVExtension/Models/WindowsIdentityService.cs b/HyperVExtension/src/HyperVExtension/Models/WindowsIdentityService.cs
index d1a7415244..6ab10f7fda 100644
--- a/HyperVExtension/src/HyperVExtension/Models/WindowsIdentityService.cs
+++ b/HyperVExtension/src/HyperVExtension/Models/WindowsIdentityService.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace HyperVExtension.Models;
public class WindowsIdentityService : IWindowsIdentityService
diff --git a/HyperVExtension/src/HyperVExtension/Models/WindowsServiceController.cs b/HyperVExtension/src/HyperVExtension/Models/WindowsServiceController.cs
index 7fbbe37aca..ec00b595e1 100644
--- a/HyperVExtension/src/HyperVExtension/Models/WindowsServiceController.cs
+++ b/HyperVExtension/src/HyperVExtension/Models/WindowsServiceController.cs
@@ -3,7 +3,6 @@
using System.ServiceProcess;
using DevHome.Logging;
-using HyperVExtension.Services;
namespace HyperVExtension.Models;
diff --git a/HyperVExtension/src/HyperVExtension/Providers/HyperVProvider.cs b/HyperVExtension/src/HyperVExtension/Providers/HyperVProvider.cs
index 89ce9251fc..2b0fb6b460 100644
--- a/HyperVExtension/src/HyperVExtension/Providers/HyperVProvider.cs
+++ b/HyperVExtension/src/HyperVExtension/Providers/HyperVProvider.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using HyperVExtension.Common;
-using HyperVExtension.Exceptions;
using HyperVExtension.Helpers;
using HyperVExtension.Services;
using Microsoft.Windows.DevHome.SDK;
diff --git a/HyperVExtension/src/HyperVExtension/Services/HyperVManager.cs b/HyperVExtension/src/HyperVExtension/Services/HyperVManager.cs
index 5655b88662..4b23e6b950 100644
--- a/HyperVExtension/src/HyperVExtension/Services/HyperVManager.cs
+++ b/HyperVExtension/src/HyperVExtension/Services/HyperVManager.cs
@@ -1,9 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Globalization;
-using System.Management.Automation;
-using System.Security.Principal;
using System.ServiceProcess;
using DevHome.Logging;
using HyperVExtension.Common.Extensions;
diff --git a/HyperVExtension/src/HyperVExtension/Services/PowerShellService.cs b/HyperVExtension/src/HyperVExtension/Services/PowerShellService.cs
index f3ef11fbe0..5ecf558ac8 100644
--- a/HyperVExtension/src/HyperVExtension/Services/PowerShellService.cs
+++ b/HyperVExtension/src/HyperVExtension/Services/PowerShellService.cs
@@ -1,14 +1,11 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
-using System.Threading;
using DevHome.Logging;
using HyperVExtension.Common;
using HyperVExtension.Models;
-using Microsoft.Extensions.Hosting;
namespace HyperVExtension.Services;
diff --git a/HyperVExtension/src/HyperVExtensionServer/Program.cs b/HyperVExtension/src/HyperVExtensionServer/Program.cs
index 94c90f3efd..91a23da88e 100644
--- a/HyperVExtension/src/HyperVExtensionServer/Program.cs
+++ b/HyperVExtension/src/HyperVExtensionServer/Program.cs
@@ -1,17 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using HyperVExtension.Common;
using HyperVExtension.Common.Extensions;
using HyperVExtension.Extensions;
using HyperVExtension.ExtensionServer;
-using HyperVExtension.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Windows.AppLifecycle;
-using Microsoft.Windows.AppNotifications;
using Windows.ApplicationModel.Activation;
-using Windows.Management.Deployment;
namespace HyperVExtension;
diff --git a/HyperVExtension/src/Logging/listeners/ListenerBase.cs b/HyperVExtension/src/Logging/listeners/ListenerBase.cs
index 53a1462691..e93d7c224b 100644
--- a/HyperVExtension/src/Logging/listeners/ListenerBase.cs
+++ b/HyperVExtension/src/Logging/listeners/ListenerBase.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using DevHome.Logging;
-
namespace DevHome.Logging.Listeners;
public abstract class ListenerBase : IListener
diff --git a/HyperVExtension/src/Telemetry/ILogger.cs b/HyperVExtension/src/Telemetry/ILogger.cs
index a7cecb85ec..c8d4867ec7 100644
--- a/HyperVExtension/src/Telemetry/ILogger.cs
+++ b/HyperVExtension/src/Telemetry/ILogger.cs
@@ -2,11 +2,7 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace HyperVExtension.Telemetry;
diff --git a/HyperVExtension/src/Telemetry/LogLevel.cs b/HyperVExtension/src/Telemetry/LogLevel.cs
index 07e6bf10a7..9496eb83ad 100644
--- a/HyperVExtension/src/Telemetry/LogLevel.cs
+++ b/HyperVExtension/src/Telemetry/LogLevel.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace HyperVExtension.Telemetry;
///
diff --git a/HyperVExtension/src/Telemetry/Logger.cs b/HyperVExtension/src/Telemetry/Logger.cs
index 0516f03fb7..6b88ddd3d4 100644
--- a/HyperVExtension/src/Telemetry/Logger.cs
+++ b/HyperVExtension/src/Telemetry/Logger.cs
@@ -3,17 +3,12 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;
using System.IO;
using System.Linq;
-using System.Reflection;
using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Input;
using Microsoft.Diagnostics.Telemetry;
-using Microsoft.Win32;
namespace HyperVExtension.Telemetry;
diff --git a/HyperVExtension/src/Telemetry/LoggerFactory.cs b/HyperVExtension/src/Telemetry/LoggerFactory.cs
index bb6b1a19ba..2c3b8d7e2c 100644
--- a/HyperVExtension/src/Telemetry/LoggerFactory.cs
+++ b/HyperVExtension/src/Telemetry/LoggerFactory.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace HyperVExtension.Telemetry;
///
diff --git a/HyperVExtension/test/DevSetupAgent.Test/DevSetupAgentIntegrationTest.cs b/HyperVExtension/test/DevSetupAgent.Test/DevSetupAgentIntegrationTest.cs
index 09ccf93005..fa208d0980 100644
--- a/HyperVExtension/test/DevSetupAgent.Test/DevSetupAgentIntegrationTest.cs
+++ b/HyperVExtension/test/DevSetupAgent.Test/DevSetupAgentIntegrationTest.cs
@@ -7,7 +7,6 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Win32;
-using Windows.UI.Accessibility;
namespace DevSetupAgent.Test;
diff --git a/HyperVExtension/test/DevSetupEngine.Test/DevSetupEngineIntegrationTest.cs b/HyperVExtension/test/DevSetupEngine.Test/DevSetupEngineIntegrationTest.cs
index 006833b30a..a7aa327f34 100644
--- a/HyperVExtension/test/DevSetupEngine.Test/DevSetupEngineIntegrationTest.cs
+++ b/HyperVExtension/test/DevSetupEngine.Test/DevSetupEngineIntegrationTest.cs
@@ -2,8 +2,6 @@
// Licensed under the MIT License.
using System.Runtime.InteropServices;
-using System.Text.Json;
-using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Win32;
using Microsoft.Windows.DevHome.DevSetupEngine;
diff --git a/HyperVExtension/test/DevSetupEngine.Test/IHostExtensions.cs b/HyperVExtension/test/DevSetupEngine.Test/IHostExtensions.cs
index 567f8a620d..bacb2dd5b4 100644
--- a/HyperVExtension/test/DevSetupEngine.Test/IHostExtensions.cs
+++ b/HyperVExtension/test/DevSetupEngine.Test/IHostExtensions.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
diff --git a/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVExtensionIntegrationTest.cs b/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVExtensionIntegrationTest.cs
index f5e1f28bf6..7674335db8 100644
--- a/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVExtensionIntegrationTest.cs
+++ b/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVExtensionIntegrationTest.cs
@@ -17,8 +17,6 @@
using Microsoft.Windows.DevHome.SDK;
using Moq;
-using Communication = HyperVExtension.CommunicationWithGuest;
-
namespace HyperVExtension.UnitTest.HyperVExtensionTests.Services;
///
diff --git a/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVManagerTest.cs b/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVManagerTest.cs
index b6d6eea435..e56427fdee 100644
--- a/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVManagerTest.cs
+++ b/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVManagerTest.cs
@@ -8,7 +8,6 @@
using HyperVExtension.Models;
using HyperVExtension.Services;
using HyperVExtension.UnitTest.Mocks;
-using Moq;
using TimeoutException = System.ServiceProcess.TimeoutException;
namespace HyperVExtension.UnitTest.HyperVExtensionTests.Services;
diff --git a/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVVirtualMachineTest.cs b/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVVirtualMachineTest.cs
index 1794a1304c..ab86cc6a09 100644
--- a/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVVirtualMachineTest.cs
+++ b/HyperVExtension/test/HyperVExtension/HyperVExtensionTests/Services/HyperVVirtualMachineTest.cs
@@ -1,10 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Collections.ObjectModel;
using System.Management.Automation;
-using System.Security.Claims;
-using System.Security.Principal;
using System.ServiceProcess;
using HyperVExtension.Common.Extensions;
using HyperVExtension.Helpers;
@@ -12,7 +9,6 @@
using HyperVExtension.Services;
using HyperVExtension.UnitTest.Mocks;
using Microsoft.Windows.DevHome.SDK;
-using Windows.System;
namespace HyperVExtension.UnitTest.HyperVExtensionTests.Services;
diff --git a/HyperVExtension/test/HyperVExtension/Mocks/PSCustomObjectMock.cs b/HyperVExtension/test/HyperVExtension/Mocks/PSCustomObjectMock.cs
index aded031154..144164fc5c 100644
--- a/HyperVExtension/test/HyperVExtension/Mocks/PSCustomObjectMock.cs
+++ b/HyperVExtension/test/HyperVExtension/Mocks/PSCustomObjectMock.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.ServiceProcess;
-
namespace HyperVExtension.UnitTest.Mocks;
public enum HyperVState
diff --git a/HyperVExtension/test/HyperVExtension/Mocks/WindowsIdentityServiceMock.cs b/HyperVExtension/test/HyperVExtension/Mocks/WindowsIdentityServiceMock.cs
index 838265d07d..59565aa423 100644
--- a/HyperVExtension/test/HyperVExtension/Mocks/WindowsIdentityServiceMock.cs
+++ b/HyperVExtension/test/HyperVExtension/Mocks/WindowsIdentityServiceMock.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Security.Claims;
using System.Security.Principal;
using HyperVExtension.Helpers;
using HyperVExtension.Models;
diff --git a/HyperVExtension/test/HyperVExtension/Usings.cs b/HyperVExtension/test/HyperVExtension/Usings.cs
index b5ac66bdaf..57cb48602a 100644
--- a/HyperVExtension/test/HyperVExtension/Usings.cs
+++ b/HyperVExtension/test/HyperVExtension/Usings.cs
@@ -2,4 +2,3 @@
// Licensed under the MIT License.
global using Microsoft.VisualStudio.TestTools.UnitTesting;
-global using Microsoft.VisualStudio.TestTools.UnitTesting.AppContainer;
diff --git a/common/Contracts/IComputeSystemService.cs b/common/Contracts/IComputeSystemService.cs
index 40948b5367..8fffd1cbb8 100644
--- a/common/Contracts/IComputeSystemService.cs
+++ b/common/Contracts/IComputeSystemService.cs
@@ -1,13 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DevHome.Common.Environments.Models;
-using DevHome.Common.Models;
-using DevHome.Common.Services;
-using Microsoft.Windows.DevHome.SDK;
namespace DevHome.Common.Contracts.Services;
diff --git a/common/Contracts/IWindowsIdentityService.cs b/common/Contracts/IWindowsIdentityService.cs
index cbc931a041..309c698dd4 100644
--- a/common/Contracts/IWindowsIdentityService.cs
+++ b/common/Contracts/IWindowsIdentityService.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace DevHome.Common.Contracts;
public interface IWindowsIdentityService
diff --git a/common/Environments/CustomControls/CardBody.xaml.cs b/common/Environments/CustomControls/CardBody.xaml.cs
index 02ace4d499..61aacbbee9 100644
--- a/common/Environments/CustomControls/CardBody.xaml.cs
+++ b/common/Environments/CustomControls/CardBody.xaml.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.ObjectModel;
using DevHome.Common.Environments.Models;
-using DevHome.Common.Windows;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Imaging;
diff --git a/common/Environments/Helpers/ComputeSystemHelpers.cs b/common/Environments/Helpers/ComputeSystemHelpers.cs
index af2d977172..354b32cee2 100644
--- a/common/Environments/Helpers/ComputeSystemHelpers.cs
+++ b/common/Environments/Helpers/ComputeSystemHelpers.cs
@@ -4,9 +4,7 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
-using System.Text;
using System.Threading.Tasks;
using DevHome.Common.Environments.Models;
using DevHome.Common.Helpers;
diff --git a/common/Environments/Helpers/StringResourceHelper.cs b/common/Environments/Helpers/StringResourceHelper.cs
index af14fc599d..6077b73c2b 100644
--- a/common/Environments/Helpers/StringResourceHelper.cs
+++ b/common/Environments/Helpers/StringResourceHelper.cs
@@ -2,10 +2,6 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using DevHome.Common.Helpers;
using DevHome.Common.Services;
diff --git a/common/Environments/Models/CardProperty.cs b/common/Environments/Models/CardProperty.cs
index 1a1644b008..8e7789fb94 100644
--- a/common/Environments/Models/CardProperty.cs
+++ b/common/Environments/Models/CardProperty.cs
@@ -4,14 +4,11 @@
using System;
using System.Globalization;
using System.IO;
-using CommunityToolkit.Common;
using CommunityToolkit.Mvvm.ComponentModel;
using DevHome.Common.Environments.Helpers;
using DevHome.Common.Helpers;
-using DevHome.Common.Services;
using Microsoft.UI.Xaml.Media.Imaging;
using Microsoft.Windows.DevHome.SDK;
-using Newtonsoft.Json.Linq;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.Shell;
diff --git a/common/Environments/Models/ComputeSystem.cs b/common/Environments/Models/ComputeSystem.cs
index e448529578..3b626d58ef 100644
--- a/common/Environments/Models/ComputeSystem.cs
+++ b/common/Environments/Models/ComputeSystem.cs
@@ -4,12 +4,10 @@
using System;
using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DevHome.Common.Environments.Helpers;
using DevHome.Common.Helpers;
-using DevHome.Common.Services;
using Microsoft.Windows.DevHome.SDK;
using Windows.Foundation;
diff --git a/common/Environments/Models/ComputeSystemProvider.cs b/common/Environments/Models/ComputeSystemProvider.cs
index ee62d0c8ee..e5e48d0a2c 100644
--- a/common/Environments/Models/ComputeSystemProvider.cs
+++ b/common/Environments/Models/ComputeSystemProvider.cs
@@ -2,18 +2,12 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using System.Xml.Linq;
using DevHome.Common.Environments.Helpers;
using DevHome.Common.Helpers;
-using DevHome.Common.Services;
using Microsoft.Windows.DevHome.SDK;
-using Windows.Foundation;
-using Windows.Foundation.Metadata;
namespace DevHome.Common.Environments.Models;
diff --git a/common/Environments/Models/ComputeSystemProviderDetails.cs b/common/Environments/Models/ComputeSystemProviderDetails.cs
index dbbf70be5e..d39a782acf 100644
--- a/common/Environments/Models/ComputeSystemProviderDetails.cs
+++ b/common/Environments/Models/ComputeSystemProviderDetails.cs
@@ -1,14 +1,9 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using DevHome.Common.Models;
using DevHome.Common.Services;
-using Microsoft.Windows.DevHome.SDK;
namespace DevHome.Common.Environments.Models;
diff --git a/common/Environments/Models/ComputeSystemsLoadedData.cs b/common/Environments/Models/ComputeSystemsLoadedData.cs
index 9b8d445c22..82441cc181 100644
--- a/common/Environments/Models/ComputeSystemsLoadedData.cs
+++ b/common/Environments/Models/ComputeSystemsLoadedData.cs
@@ -3,7 +3,6 @@
using System.Collections.Generic;
using DevHome.Common.Models;
-using DevHome.Common.Services;
using Microsoft.Windows.DevHome.SDK;
namespace DevHome.Common.Environments.Models;
diff --git a/common/Environments/Services/ComputeSystemManager.cs b/common/Environments/Services/ComputeSystemManager.cs
index 53f017225b..38c493002f 100644
--- a/common/Environments/Services/ComputeSystemManager.cs
+++ b/common/Environments/Services/ComputeSystemManager.cs
@@ -3,14 +3,12 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using DevHome.Common.Contracts.Services;
using DevHome.Common.Environments.Models;
using DevHome.Common.Helpers;
using DevHome.Common.Models;
-using DevHome.Common.Services;
using Microsoft.Windows.DevHome.SDK;
using Windows.Foundation;
diff --git a/common/Environments/Services/IComputeSystemManager.cs b/common/Environments/Services/IComputeSystemManager.cs
index 1592d4724e..40c6c7c8c8 100644
--- a/common/Environments/Services/IComputeSystemManager.cs
+++ b/common/Environments/Services/IComputeSystemManager.cs
@@ -2,8 +2,6 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Linq;
using System.Threading.Tasks;
using DevHome.Common.Environments.Models;
using Microsoft.Windows.DevHome.SDK;
diff --git a/common/Helpers/EnumHelper.cs b/common/Helpers/EnumHelper.cs
index a8fbfcc28a..3e7f268eaf 100644
--- a/common/Helpers/EnumHelper.cs
+++ b/common/Helpers/EnumHelper.cs
@@ -3,10 +3,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Newtonsoft.Json.Linq;
namespace DevHome.Common.Helpers;
diff --git a/common/Models/ProviderOperationResultWrapper.cs b/common/Models/ProviderOperationResultWrapper.cs
index c490e33a2b..0119febb4f 100644
--- a/common/Models/ProviderOperationResultWrapper.cs
+++ b/common/Models/ProviderOperationResultWrapper.cs
@@ -2,10 +2,6 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Microsoft.Windows.DevHome.SDK;
namespace DevHome.Common.Models;
diff --git a/common/Services/ComputeSystemService.cs b/common/Services/ComputeSystemService.cs
index 196c7eaec4..c88c1c6a89 100644
--- a/common/Services/ComputeSystemService.cs
+++ b/common/Services/ComputeSystemService.cs
@@ -4,11 +4,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
using DevHome.Common.Contracts.Services;
using DevHome.Common.Environments.Models;
-using DevHome.Common.Helpers;
using DevHome.Common.Models;
using DevHome.Logging;
using Microsoft.Windows.DevHome.SDK;
diff --git a/common/Services/LocalSettingsService.cs b/common/Services/LocalSettingsService.cs
index 46a1fb3eb5..3bd1a6ca30 100644
--- a/common/Services/LocalSettingsService.cs
+++ b/common/Services/LocalSettingsService.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Threading.Tasks;
using DevHome.Common.Contracts;
using DevHome.Common.Helpers;
diff --git a/common/Services/ToastNotificationService.cs b/common/Services/ToastNotificationService.cs
index c8d15f6de2..c618068c76 100644
--- a/common/Services/ToastNotificationService.cs
+++ b/common/Services/ToastNotificationService.cs
@@ -2,12 +2,7 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using DevHome.Common.Contracts;
using DevHome.Common.Environments.Helpers;
using DevHome.Common.Helpers;
@@ -15,8 +10,6 @@
using Microsoft.Windows.AppNotifications;
using Microsoft.Windows.AppNotifications.Builder;
using Windows.ApplicationModel.Activation;
-using Windows.Media.AppBroadcasting;
-using WinUIEx.Messaging;
namespace DevHome.Common.Services;
diff --git a/common/Services/WindowsIdentityService.cs b/common/Services/WindowsIdentityService.cs
index 26f5ad268a..5503a1e26d 100644
--- a/common/Services/WindowsIdentityService.cs
+++ b/common/Services/WindowsIdentityService.cs
@@ -1,12 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
-using System.Text;
-using System.Threading.Tasks;
using DevHome.Common.Contracts;
namespace DevHome.Common.Services;
diff --git a/logging/listeners/ListenerBase.cs b/logging/listeners/ListenerBase.cs
index 7e3c927e82..7d6a500662 100644
--- a/logging/listeners/ListenerBase.cs
+++ b/logging/listeners/ListenerBase.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using DevHome.Logging;
-
namespace DevHome.Logging.Listeners;
public abstract class ListenerBase : IListener
diff --git a/settings/DevHome.Settings/ViewModels/ExperimentalFeaturesViewModel.cs b/settings/DevHome.Settings/ViewModels/ExperimentalFeaturesViewModel.cs
index 000b862054..b27a3e7009 100644
--- a/settings/DevHome.Settings/ViewModels/ExperimentalFeaturesViewModel.cs
+++ b/settings/DevHome.Settings/ViewModels/ExperimentalFeaturesViewModel.cs
@@ -8,7 +8,6 @@
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Models;
using DevHome.Common.Services;
-using DevHome.Settings.Models;
using Microsoft.UI.Xaml.Controls;
namespace DevHome.Settings.ViewModels;
diff --git a/src/MainWindow.xaml.cs b/src/MainWindow.xaml.cs
index 7f7ef0a508..2760f43865 100644
--- a/src/MainWindow.xaml.cs
+++ b/src/MainWindow.xaml.cs
@@ -3,7 +3,6 @@
using DevHome.Common.Extensions;
using DevHome.Common.Services;
-using DevHome.Helpers;
using DevHome.Telemetry;
using DevHome.TelemetryEvents;
using Microsoft.UI.Xaml;
diff --git a/src/Services/ExtensionService.cs b/src/Services/ExtensionService.cs
index 7664767677..0566a581bf 100644
--- a/src/Services/ExtensionService.cs
+++ b/src/Services/ExtensionService.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Xml.Linq;
using DevHome.Common.Contracts;
using DevHome.Common.Extensions;
using DevHome.Common.Services;
diff --git a/src/Services/ProtocolActivationHandler.cs b/src/Services/ProtocolActivationHandler.cs
index 336078f789..16efdf1866 100644
--- a/src/Services/ProtocolActivationHandler.cs
+++ b/src/Services/ProtocolActivationHandler.cs
@@ -1,11 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using DevHome.Activation;
using DevHome.Common.Services;
using DevHome.Settings.ViewModels;
diff --git a/src/ViewModels/InfoBarModel.cs b/src/ViewModels/InfoBarModel.cs
index b199f43fbd..694bc14649 100644
--- a/src/ViewModels/InfoBarModel.cs
+++ b/src/ViewModels/InfoBarModel.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Xaml.Controls;
diff --git a/src/Views/ShellPage.xaml.cs b/src/Views/ShellPage.xaml.cs
index 6e4a690a6f..b9d81fc8ca 100644
--- a/src/Views/ShellPage.xaml.cs
+++ b/src/Views/ShellPage.xaml.cs
@@ -5,7 +5,6 @@
using DevHome.Common.Helpers;
using DevHome.Common.Models;
using DevHome.Common.Services;
-using DevHome.Settings.ViewModels;
using DevHome.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
diff --git a/telemetry/DevHome.Telemetry/LogLevel.cs b/telemetry/DevHome.Telemetry/LogLevel.cs
index 3de5326b94..3f3432f33e 100644
--- a/telemetry/DevHome.Telemetry/LogLevel.cs
+++ b/telemetry/DevHome.Telemetry/LogLevel.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace DevHome.Telemetry;
///
diff --git a/test/GitWatcherTests.cs b/test/GitWatcherTests.cs
index 420765fd28..155a43db4b 100644
--- a/test/GitWatcherTests.cs
+++ b/test/GitWatcherTests.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using System.Collections.ObjectModel;
-using System.Diagnostics;
using System.Globalization;
using DevHome.Contracts.Services;
using DevHome.Services;
diff --git a/test/TestClass.cs b/test/TestClass.cs
index 614faf7a14..a67af0e1fb 100644
--- a/test/TestClass.cs
+++ b/test/TestClass.cs
@@ -3,8 +3,6 @@
using System.Diagnostics;
-using Microsoft.UI.Xaml.Controls;
-
namespace DevHome.Test;
/*
diff --git a/tools/Dashboard/DevHome.Dashboard/Controls/SelectableMenuFlyoutItem.cs b/tools/Dashboard/DevHome.Dashboard/Controls/SelectableMenuFlyoutItem.cs
index eb5decbf46..10237c3949 100644
--- a/tools/Dashboard/DevHome.Dashboard/Controls/SelectableMenuFlyoutItem.cs
+++ b/tools/Dashboard/DevHome.Dashboard/Controls/SelectableMenuFlyoutItem.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Automation.Provider;
diff --git a/tools/Environments/DevHome.Environments/CustomControls/CardFlyout.xaml.cs b/tools/Environments/DevHome.Environments/CustomControls/CardFlyout.xaml.cs
index dd56e79ce2..84f5c3eac6 100644
--- a/tools/Environments/DevHome.Environments/CustomControls/CardFlyout.xaml.cs
+++ b/tools/Environments/DevHome.Environments/CustomControls/CardFlyout.xaml.cs
@@ -3,7 +3,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using CommunityToolkit.Mvvm.Input;
using DevHome.Environments.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
diff --git a/tools/Environments/DevHome.Environments/Extensions/ServiceExtensions.cs b/tools/Environments/DevHome.Environments/Extensions/ServiceExtensions.cs
index b3963a4387..31d498c05d 100644
--- a/tools/Environments/DevHome.Environments/Extensions/ServiceExtensions.cs
+++ b/tools/Environments/DevHome.Environments/Extensions/ServiceExtensions.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using DevHome.Common.Contracts;
-using DevHome.Common.Contracts.Services;
using DevHome.Common.Services;
using DevHome.Environments.Helpers;
using DevHome.Environments.Models;
diff --git a/tools/Environments/DevHome.Environments/Helpers/DataExtractor.cs b/tools/Environments/DevHome.Environments/Helpers/DataExtractor.cs
index fee6a4a6f3..e2bb9de5db 100644
--- a/tools/Environments/DevHome.Environments/Helpers/DataExtractor.cs
+++ b/tools/Environments/DevHome.Environments/Helpers/DataExtractor.cs
@@ -1,20 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Runtime.InteropServices.WindowsRuntime;
-using System.Runtime.Intrinsics.Arm;
-using System.Threading.Tasks;
-using CommunityToolkit.WinUI.Animations;
using DevHome.Common.Environments.Models;
using DevHome.Environments.ViewModels;
-using Microsoft.UI.Xaml.Media.Imaging;
using Microsoft.Windows.DevHome.SDK;
-using Windows.Graphics.Imaging;
-using Windows.Storage.Streams;
namespace DevHome.Environments.Helpers;
diff --git a/tools/Environments/DevHome.Environments/Helpers/EnvironmentsExtensionsService.cs b/tools/Environments/DevHome.Environments/Helpers/EnvironmentsExtensionsService.cs
index fb3894b7eb..c06c98146a 100644
--- a/tools/Environments/DevHome.Environments/Helpers/EnvironmentsExtensionsService.cs
+++ b/tools/Environments/DevHome.Environments/Helpers/EnvironmentsExtensionsService.cs
@@ -3,18 +3,12 @@
using System;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
using System.Threading.Tasks;
-using DevHome.Common.Contracts.Services;
using DevHome.Common.Environments.Models;
using DevHome.Common.Environments.Services;
using DevHome.Common.Extensions;
using DevHome.Common.Models;
-using DevHome.Common.Services;
using DevHome.Environments.TestModels;
-using DevHome.Environments.ViewModels;
-using DevHome.Logging;
using Microsoft.UI.Xaml;
using Microsoft.Windows.DevHome.SDK;
diff --git a/tools/Environments/DevHome.Environments/TestModels/EmptyDevId.cs b/tools/Environments/DevHome.Environments/TestModels/EmptyDevId.cs
index 2cccbeafd6..2ef51cee89 100644
--- a/tools/Environments/DevHome.Environments/TestModels/EmptyDevId.cs
+++ b/tools/Environments/DevHome.Environments/TestModels/EmptyDevId.cs
@@ -1,11 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Microsoft.Windows.DevHome.SDK;
namespace DevHome.Environments.TestModels;
diff --git a/tools/Environments/DevHome.Environments/TestModels/TestExtensionWrapper.cs b/tools/Environments/DevHome.Environments/TestModels/TestExtensionWrapper.cs
index 638aceaedb..aba63a03af 100644
--- a/tools/Environments/DevHome.Environments/TestModels/TestExtensionWrapper.cs
+++ b/tools/Environments/DevHome.Environments/TestModels/TestExtensionWrapper.cs
@@ -3,8 +3,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
using System.Threading.Tasks;
using DevHome.Common.Services;
using Microsoft.Windows.DevHome.SDK;
diff --git a/tools/Environments/DevHome.Environments/TestModels/TestSystems.cs b/tools/Environments/DevHome.Environments/TestModels/TestSystems.cs
index 27e3280124..567b4a9417 100644
--- a/tools/Environments/DevHome.Environments/TestModels/TestSystems.cs
+++ b/tools/Environments/DevHome.Environments/TestModels/TestSystems.cs
@@ -3,12 +3,10 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Microsoft.Windows.DevHome.SDK;
using Windows.Foundation;
-using Windows.Graphics.Imaging;
using Windows.Storage;
using Windows.Storage.Streams;
diff --git a/tools/Environments/DevHome.Environments/ViewModels/ComputeSystemViewModel.cs b/tools/Environments/DevHome.Environments/ViewModels/ComputeSystemViewModel.cs
index fe844cfccc..50f417e3f4 100644
--- a/tools/Environments/DevHome.Environments/ViewModels/ComputeSystemViewModel.cs
+++ b/tools/Environments/DevHome.Environments/ViewModels/ComputeSystemViewModel.cs
@@ -1,10 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Diagnostics;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
diff --git a/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs b/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs
index 04b085098b..f483d3ab7b 100644
--- a/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs
+++ b/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs
@@ -2,24 +2,18 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI;
using CommunityToolkit.WinUI.Collections;
-using DevHome.Common.Environments.Helpers;
using DevHome.Common.Environments.Models;
using DevHome.Common.Environments.Services;
-using DevHome.Common.Extensions;
using DevHome.Common.Helpers;
using DevHome.Common.Services;
using DevHome.Environments.Helpers;
-using Microsoft.UI.Xaml;
-using WinUIEx;
namespace DevHome.Environments.ViewModels;
diff --git a/tools/Environments/DevHome.Environments/ViewModels/OperationsViewModel.cs b/tools/Environments/DevHome.Environments/ViewModels/OperationsViewModel.cs
index bf33c9fe7d..4b87fa35f9 100644
--- a/tools/Environments/DevHome.Environments/ViewModels/OperationsViewModel.cs
+++ b/tools/Environments/DevHome.Environments/ViewModels/OperationsViewModel.cs
@@ -4,9 +4,7 @@
using System;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
-using Microsoft.UI.Xaml;
using Microsoft.Windows.DevHome.SDK;
-using Windows.Foundation;
namespace DevHome.Environments.ViewModels;
diff --git a/tools/Environments/DevHome.Environments/Views/LandingPage.xaml.cs b/tools/Environments/DevHome.Environments/Views/LandingPage.xaml.cs
index 2583b386de..2936f5a52f 100644
--- a/tools/Environments/DevHome.Environments/Views/LandingPage.xaml.cs
+++ b/tools/Environments/DevHome.Environments/Views/LandingPage.xaml.cs
@@ -1,22 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Linq;
-using System.Management.Automation.Runspaces;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
using DevHome.Common;
-using DevHome.Common.Contracts;
using DevHome.Common.Extensions;
-using DevHome.Common.Services;
-using DevHome.Environments.Helpers;
using DevHome.Environments.ViewModels;
using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
-using Microsoft.Windows.AppNotifications;
-using Microsoft.Windows.AppNotifications.Builder;
-using Microsoft.Windows.DevHome.SDK;
namespace DevHome.Environments.Views;
diff --git a/tools/Experiments/src/ViewModels/TestExperimentViewModel.cs b/tools/Experiments/src/ViewModels/TestExperimentViewModel.cs
index b9bd69a393..0e249dfe4e 100644
--- a/tools/Experiments/src/ViewModels/TestExperimentViewModel.cs
+++ b/tools/Experiments/src/ViewModels/TestExperimentViewModel.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace DevHome.Experiments.ViewModels;
public class TestExperimentViewModel
diff --git a/tools/Experiments/src/Views/TestExperimentPage.xaml.cs b/tools/Experiments/src/Views/TestExperimentPage.xaml.cs
index 7d0540d2f1..7957848107 100644
--- a/tools/Experiments/src/Views/TestExperimentPage.xaml.cs
+++ b/tools/Experiments/src/Views/TestExperimentPage.xaml.cs
@@ -1,22 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices.WindowsRuntime;
using DevHome.Common;
using DevHome.Experiments.ViewModels;
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Controls.Primitives;
-using Microsoft.UI.Xaml.Data;
-using Microsoft.UI.Xaml.Input;
-using Microsoft.UI.Xaml.Media;
-using Microsoft.UI.Xaml.Navigation;
-using Windows.Foundation;
-using Windows.Foundation.Collections;
namespace DevHome.Experiments.Views;
diff --git a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/InstalledPackageViewModel.cs b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/InstalledPackageViewModel.cs
index e0637370f6..21da871689 100644
--- a/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/InstalledPackageViewModel.cs
+++ b/tools/ExtensionLibrary/DevHome.ExtensionLibrary/ViewModels/InstalledPackageViewModel.cs
@@ -9,7 +9,6 @@
using DevHome.Common.Contracts;
using DevHome.Common.Extensions;
using DevHome.Common.Services;
-using DevHome.Telemetry;
using Microsoft.UI.Xaml;
using Windows.ApplicationModel;
using Windows.System;
diff --git a/tools/SampleTool/src/Class1.cs b/tools/SampleTool/src/Class1.cs
index 5e9c602dcd..d797686c3a 100644
--- a/tools/SampleTool/src/Class1.cs
+++ b/tools/SampleTool/src/Class1.cs
@@ -1,12 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
namespace SampleTool;
public class Class1
diff --git a/tools/SampleTool/unittest/TestClass.cs b/tools/SampleTool/unittest/TestClass.cs
index 920fd8b452..57c39fb288 100644
--- a/tools/SampleTool/unittest/TestClass.cs
+++ b/tools/SampleTool/unittest/TestClass.cs
@@ -3,8 +3,6 @@
using System.Diagnostics;
-using Microsoft.UI.Xaml.Controls;
-
namespace SampleTool.Test;
[TestClass]
diff --git a/tools/SetupFlow/DevHome.SetupFlow.ElevatedComponent/Helpers/ElevatedConfigureUnitTaskResult.cs b/tools/SetupFlow/DevHome.SetupFlow.ElevatedComponent/Helpers/ElevatedConfigureUnitTaskResult.cs
index 2401402117..cf56009d34 100644
--- a/tools/SetupFlow/DevHome.SetupFlow.ElevatedComponent/Helpers/ElevatedConfigureUnitTaskResult.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow.ElevatedComponent/Helpers/ElevatedConfigureUnitTaskResult.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Microsoft.Management.Configuration;
-
namespace DevHome.SetupFlow.ElevatedComponent.Helpers;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow.ElevatedComponent/Tasks/ElevatedInstallTask.cs b/tools/SetupFlow/DevHome.SetupFlow.ElevatedComponent/Tasks/ElevatedInstallTask.cs
index 3ee73240c4..a626faf63a 100644
--- a/tools/SetupFlow/DevHome.SetupFlow.ElevatedComponent/Tasks/ElevatedInstallTask.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow.ElevatedComponent/Tasks/ElevatedInstallTask.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using DevHome.Logging;
using DevHome.SetupFlow.Common.Extensions;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Common.WindowsPackageManager;
diff --git a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/AddRepoDialogTests.cs b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/AddRepoDialogTests.cs
index 7b2314374b..21006cc5fb 100644
--- a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/AddRepoDialogTests.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/AddRepoDialogTests.cs
@@ -6,7 +6,6 @@
using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.Services;
using DevHome.SetupFlow.ViewModels;
-using Microsoft.UI.Xaml;
namespace DevHome.SetupFlow.UnitTest;
diff --git a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/DevDriveEnumToLocalizedStringConverterTest.cs b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/DevDriveEnumToLocalizedStringConverterTest.cs
index 42cf5fc604..be90228c53 100644
--- a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/DevDriveEnumToLocalizedStringConverterTest.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/DevDriveEnumToLocalizedStringConverterTest.cs
@@ -1,9 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Linq;
using DevHome.Common.Services;
-using DevHome.SetupFlow.Services;
using DevHome.SetupFlow.Utilities;
namespace DevHome.SetupFlow.UnitTest;
diff --git a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/LoadingScreenTests.cs b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/LoadingScreenTests.cs
index 5e36353d7a..7ec2147faf 100644
--- a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/LoadingScreenTests.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/LoadingScreenTests.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using DevHome.Common.Extensions;
-using DevHome.SetupFlow.Services;
using DevHome.SetupFlow.ViewModels;
namespace DevHome.SetupFlow.UnitTest;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Exceptions/SDKApplyConfigurationSetResultException.cs b/tools/SetupFlow/DevHome.SetupFlow/Exceptions/SDKApplyConfigurationSetResultException.cs
index 616135b669..dd14b873fe 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Exceptions/SDKApplyConfigurationSetResultException.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Exceptions/SDKApplyConfigurationSetResultException.cs
@@ -2,10 +2,6 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace DevHome.SetupFlow.Exceptions;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Exceptions/SDKOpenConfigurationSetResultException.cs b/tools/SetupFlow/DevHome.SetupFlow/Exceptions/SDKOpenConfigurationSetResultException.cs
index 6e35371fbc..1161a18d0e 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Exceptions/SDKOpenConfigurationSetResultException.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Exceptions/SDKOpenConfigurationSetResultException.cs
@@ -2,10 +2,6 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace DevHome.SetupFlow.Exceptions;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs
index b8c8c647f8..1b906a46c9 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs
@@ -5,13 +5,11 @@
using System.IO;
using DevHome.Common.Services;
using DevHome.SetupFlow.Common.WindowsPackageManager;
-using DevHome.SetupFlow.Models.Environments;
using DevHome.SetupFlow.Services;
using DevHome.SetupFlow.Services.WinGet;
using DevHome.SetupFlow.Services.WinGet.Operations;
using DevHome.SetupFlow.TaskGroups;
using DevHome.SetupFlow.ViewModels;
-using DevHome.SetupFlow.ViewModels.Environments;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ActionCenterMessages.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ActionCenterMessages.cs
index 080559f96a..be98c6fc79 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/ActionCenterMessages.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ActionCenterMessages.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using DevHome.Common.Views;
-using Microsoft.Windows.DevHome.SDK;
namespace DevHome.SetupFlow.Models;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs
index 71eec40e4c..8f353caef5 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs
@@ -12,7 +12,6 @@
using DevHome.Common.Services;
using DevHome.Common.TelemetryEvents;
using DevHome.Common.TelemetryEvents.SetupFlow;
-using DevHome.Common.Views;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Services;
using DevHome.Telemetry;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigurationUnitResult.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigurationUnitResult.cs
index 147208fadb..9295ba296d 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigurationUnitResult.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigurationUnitResult.cs
@@ -3,7 +3,6 @@
extern alias Projection;
-using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Management.Configuration;
using Projection::DevHome.SetupFlow.ElevatedComponent.Helpers;
using Windows.Win32.Foundation;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs
index 25cb50a494..dcb98ac2c0 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs
@@ -5,16 +5,12 @@
using System;
using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AdaptiveCards.Rendering.WinUI3;
using CommunityToolkit.WinUI;
-using DevHome.Common.Environments.Models;
using DevHome.Common.Environments.Services;
-using DevHome.Common.Renderers;
using DevHome.Common.Views;
using DevHome.Contracts.Services;
using DevHome.Logging;
@@ -23,14 +19,11 @@
using DevHome.SetupFlow.Exceptions;
using DevHome.SetupFlow.Models.WingetConfigure;
using DevHome.SetupFlow.Services;
-using LibGit2Sharp;
using Microsoft.UI.Xaml;
using Microsoft.Windows.DevHome.SDK;
using Projection::DevHome.SetupFlow.ElevatedComponent;
using Windows.Foundation;
using Windows.Storage;
-using Windows.Win32;
-using WinUIEx;
using SDK = Microsoft.Windows.DevHome.SDK;
namespace DevHome.SetupFlow.Models;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTask.cs
index c0b3c481ce..5f7ca31d58 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTask.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTask.cs
@@ -8,7 +8,6 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
-using DevHome.Common.Views;
using DevHome.SetupFlow.Common.Contracts;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Services;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CreateDevDriveTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CreateDevDriveTask.cs
index 36e2b27722..7f3e7205ac 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/CreateDevDriveTask.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CreateDevDriveTask.cs
@@ -12,7 +12,6 @@
using DevHome.Common.Models;
using DevHome.Common.ResultHelper;
using DevHome.Common.Services;
-using DevHome.Common.Views;
using DevHome.SetupFlow.Common.Contracts;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Common.TelemetryEvents;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs
index b306d683b3..f774d6e77c 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ISetupTask.cs
@@ -3,10 +3,6 @@
extern alias Projection;
-using System;
-using DevHome.Common.Views;
-using DevHome.SetupFlow.ViewModels;
-using Microsoft.Windows.DevHome.SDK;
using Projection::DevHome.SetupFlow.ElevatedComponent;
using Windows.Foundation;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/IWinGetPackage.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/IWinGetPackage.cs
index 2d96f8e737..04ae8c6d00 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/IWinGetPackage.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/IWinGetPackage.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using DevHome.SetupFlow.Common.WindowsPackageManager;
using DevHome.SetupFlow.Services;
using Windows.Storage.Streams;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/InstallPackageTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/InstallPackageTask.cs
index 2f85b4acd1..7920edf38a 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/InstallPackageTask.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/InstallPackageTask.cs
@@ -6,7 +6,6 @@
using System;
using System.Threading.Tasks;
using DevHome.Common.TelemetryEvents.SetupFlow;
-using DevHome.Common.Views;
using DevHome.SetupFlow.Common.Contracts;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Exceptions;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProviders.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProviders.cs
index d68dec38d4..4725551e91 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProviders.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/RepositoryProviders.cs
@@ -11,7 +11,6 @@
using DevHome.Telemetry;
using Microsoft.UI.Xaml;
using Microsoft.Windows.DevHome.SDK;
-using Windows.Foundation;
namespace DevHome.SetupFlow.Models;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/TaskInformation.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/TaskInformation.cs
index 1be9d32112..70f0e0fe6d 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/TaskInformation.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/TaskInformation.cs
@@ -2,9 +2,6 @@
// Licensed under the MIT License.
using CommunityToolkit.Mvvm.ComponentModel;
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Media;
-using Microsoft.UI.Xaml.Media.Imaging;
namespace DevHome.SetupFlow.Models;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/GitDscSettings.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/GitDscSettings.cs
index 83155fbf80..aac7371631 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/GitDscSettings.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/GitDscSettings.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Newtonsoft.Json;
-
namespace DevHome.SetupFlow.Models.WingetConfigure;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKApplyConfigurationResult.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKApplyConfigurationResult.cs
index 3c7ad3e84e..72265dc164 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKApplyConfigurationResult.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKApplyConfigurationResult.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using Microsoft.Windows.DevHome.SDK;
namespace DevHome.SetupFlow.Models.WingetConfigure;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKApplyConfigurationSetResult.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKApplyConfigurationSetResult.cs
index fbe722f25f..c18c0885c7 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKApplyConfigurationSetResult.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKApplyConfigurationSetResult.cs
@@ -2,10 +2,7 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using DevHome.SetupFlow.Exceptions;
using SDK = Microsoft.Windows.DevHome.SDK;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKConfigurationSetChangeWrapper.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKConfigurationSetChangeWrapper.cs
index 8ee9fee759..bd74017946 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKConfigurationSetChangeWrapper.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKConfigurationSetChangeWrapper.cs
@@ -1,12 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
using System.Globalization;
-using System.Linq;
using System.Text;
-using System.Threading.Tasks;
using DevHome.SetupFlow.Services;
using SDK = Microsoft.Windows.DevHome.SDK;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKConfigurationUnitWrapper.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKConfigurationUnitWrapper.cs
index 25739ef2c6..b2d0d50485 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKConfigurationUnitWrapper.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKConfigurationUnitWrapper.cs
@@ -1,11 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using SDK = Microsoft.Windows.DevHome.SDK;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKOpenConfigurationSetResult.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKOpenConfigurationSetResult.cs
index abd04e6dce..f8e7b5c6ad 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKOpenConfigurationSetResult.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/SDKOpenConfigurationSetResult.cs
@@ -2,12 +2,7 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using DevHome.SetupFlow.Common.Helpers;
-using DevHome.SetupFlow.Exceptions;
using DevHome.SetupFlow.Services;
using SDK = Microsoft.Windows.DevHome.SDK;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigAssertion.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigAssertion.cs
index 5823843928..84da2c2ad7 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigAssertion.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigAssertion.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Newtonsoft.Json;
-
namespace DevHome.SetupFlow.Models.WingetConfigure;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigFile.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigFile.cs
index 111f4f61ec..64eec363d5 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigFile.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigFile.cs
@@ -1,13 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Newtonsoft.Json;
-
namespace DevHome.SetupFlow.Models.WingetConfigure;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigProperties.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigProperties.cs
index 9c814f1de8..2b3b57fbcb 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigProperties.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigProperties.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Newtonsoft.Json;
-
namespace DevHome.SetupFlow.Models.WingetConfigure;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigResource.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigResource.cs
index 40e3836d8f..b1b935a633 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigResource.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigResource.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Newtonsoft.Json;
-
namespace DevHome.SetupFlow.Models.WingetConfigure;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigSettingsBase.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigSettingsBase.cs
index 7a7356d675..b5a1f4fb4d 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigSettingsBase.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetConfigSettingsBase.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Newtonsoft.Json;
-
namespace DevHome.SetupFlow.Models.WingetConfigure;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetDscSettings.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetDscSettings.cs
index 03a295cd87..cd30b5508c 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetDscSettings.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WinGetDscSettings.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Newtonsoft.Json;
-
namespace DevHome.SetupFlow.Models.WingetConfigure;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WingGetConfigDirectives.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WingGetConfigDirectives.cs
index ec154cf784..7f10db9839 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WingGetConfigDirectives.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Models/WingetConfigure/WingGetConfigDirectives.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using Newtonsoft.Json;
-
namespace DevHome.SetupFlow.Models.WingetConfigure;
///
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Selectors/Environments/ComputeSystemsListViewModelSelector.cs b/tools/SetupFlow/DevHome.SetupFlow/Selectors/Environments/ComputeSystemsListViewModelSelector.cs
index d946cbbdaf..337e62ae22 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Selectors/Environments/ComputeSystemsListViewModelSelector.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Selectors/Environments/ComputeSystemsListViewModelSelector.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using DevHome.Common.Services;
using DevHome.SetupFlow.Models.Environments;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/ComputeSystemViewModelFactory.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/ComputeSystemViewModelFactory.cs
index 3a68e98381..939b992358 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Services/ComputeSystemViewModelFactory.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Services/ComputeSystemViewModelFactory.cs
@@ -2,7 +2,6 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
using System.Threading.Tasks;
using DevHome.Common.Environments.Helpers;
using DevHome.Common.Environments.Models;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/ConfigurationFileBuilder.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/ConfigurationFileBuilder.cs
index a05552dba6..0faf1612b3 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Services/ConfigurationFileBuilder.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Services/ConfigurationFileBuilder.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading.Tasks;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.Models.WingetConfigure;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/IWindowsPackageManager.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/IWindowsPackageManager.cs
index cccbb46b85..78c211ccc9 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Services/IWindowsPackageManager.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Services/IWindowsPackageManager.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DevHome.SetupFlow.Models;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/SetupFlowOrchestrator.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/SetupFlowOrchestrator.cs
index 30759bb0cf..b45bba227b 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Services/SetupFlowOrchestrator.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Services/SetupFlowOrchestrator.cs
@@ -14,7 +14,6 @@
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.ViewModels;
-using Microsoft.UI.Xaml.Controls;
using Projection::DevHome.SetupFlow.ElevatedComponent;
namespace DevHome.SetupFlow.Services;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/WinGet/Operations/WinGetGetPackageOperation.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/WinGet/Operations/WinGetGetPackageOperation.cs
index 681918dfbf..de8524b28f 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Services/WinGet/Operations/WinGetGetPackageOperation.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Services/WinGet/Operations/WinGetGetPackageOperation.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/WinGetPackageDataSource.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/WinGetPackageDataSource.cs
index 0905c49155..d326837d45 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Services/WinGetPackageDataSource.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Services/WinGetPackageDataSource.cs
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/DevDriveTaskGroup.cs b/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/DevDriveTaskGroup.cs
index 2598b71e43..5d20d74d4d 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/DevDriveTaskGroup.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/DevDriveTaskGroup.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using DevHome.Common.Extensions;
using DevHome.Common.Models;
using DevHome.Common.Services;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/RepoConfigTaskGroup.cs b/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/RepoConfigTaskGroup.cs
index 5b529fe750..b957cd4245 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/RepoConfigTaskGroup.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/RepoConfigTaskGroup.cs
@@ -10,7 +10,6 @@
using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.Services;
using DevHome.SetupFlow.ViewModels;
-using DevHome.Telemetry;
using Microsoft.Extensions.Hosting;
namespace DevHome.SetupFlow.TaskGroups;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/SetupTargetTaskGroup.cs b/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/SetupTargetTaskGroup.cs
index 62c622db1a..ece81ce14c 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/SetupTargetTaskGroup.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/TaskGroups/SetupTargetTaskGroup.cs
@@ -1,21 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
using DevHome.Common.Environments.Services;
-using DevHome.Common.Extensions;
-using DevHome.Common.Models;
-using DevHome.Common.Services;
using DevHome.Contracts.Services;
-using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.Services;
using DevHome.SetupFlow.ViewModels;
-using DevHome.SetupFlow.Views;
-using Microsoft.Extensions.Hosting;
namespace DevHome.SetupFlow.TaskGroups;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemsListViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemsListViewModel.cs
index 8e6d6fe4f9..d219dfdced 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemsListViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemsListViewModel.cs
@@ -5,13 +5,11 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
-using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI.Collections;
using DevHome.Common.Environments.Models;
using DevHome.Common.Models;
-using DevHome.Common.Services;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.ViewModels.Environments;
using Microsoft.Windows.DevHome.SDK;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingMessageViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingMessageViewModel.cs
index 462137066d..1818dcc6fe 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingMessageViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingMessageViewModel.cs
@@ -3,10 +3,7 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
-using DevHome.Common.Views;
-using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
-using Microsoft.Windows.DevHome.SDK;
namespace DevHome.SetupFlow.ViewModels;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs
index 44b2de5eb4..ac56134bac 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/LoadingViewModel.cs
@@ -8,15 +8,11 @@
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
-using AdaptiveCards.Rendering.WinUI3;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Extensions;
-using DevHome.Common.Renderers;
using DevHome.Common.TelemetryEvents.SetupFlow;
-using DevHome.Common.Views;
using DevHome.Contracts.Services;
-using DevHome.Logging;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.Services;
@@ -24,13 +20,8 @@
using DevHome.Telemetry;
using Microsoft.Extensions.Hosting;
using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Media.Imaging;
-using Microsoft.Windows.DevHome.SDK;
-using Windows.Foundation;
-using Windows.Storage;
using WinUIEx;
-using WinUIEx.Messaging;
namespace DevHome.SetupFlow.ViewModels;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ReviewViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ReviewViewModel.cs
index 1e92533f82..8b051d3484 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ReviewViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/ReviewViewModel.cs
@@ -9,16 +9,12 @@
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
-using DevHome.SetupFlow.Common.Contracts;
-using DevHome.SetupFlow.Common.Elevation;
using DevHome.SetupFlow.Common.Helpers;
using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.Services;
using DevHome.SetupFlow.TaskGroups;
using Microsoft.Extensions.Hosting;
-using Projection::DevHome.SetupFlow.ElevatedComponent;
-
namespace DevHome.SetupFlow.ViewModels;
public partial class ReviewViewModel : SetupPageViewModelBase
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupFlowViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupFlowViewModel.cs
index c5773496b7..e55d8dd73f 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupFlowViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupFlowViewModel.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Extensions;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetReviewViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetReviewViewModel.cs
index a3590fc3df..af2bc92fa7 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetReviewViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetReviewViewModel.cs
@@ -1,16 +1,12 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
-using System.Linq;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using DevHome.Common.Environments.Models;
using DevHome.Common.Environments.Services;
-using DevHome.SetupFlow.Models;
using DevHome.SetupFlow.Services;
-using DevHome.SetupFlow.TaskGroups;
using Microsoft.Windows.DevHome.SDK;
namespace DevHome.SetupFlow.ViewModels;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs
index 04d1de8262..523e3b4a48 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs
@@ -2,10 +2,7 @@
// Licensed under the MIT License.
using System;
-using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Linq;
-using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
@@ -13,13 +10,10 @@
using CommunityToolkit.WinUI.Collections;
using DevHome.Common.Environments.Models;
using DevHome.Common.Environments.Services;
-using DevHome.Common.Models;
using DevHome.Common.Services;
using DevHome.SetupFlow.Common.Helpers;
-using DevHome.SetupFlow.Exceptions;
using DevHome.SetupFlow.Models.Environments;
using DevHome.SetupFlow.Services;
-using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.DevHome.SDK;
namespace DevHome.SetupFlow.ViewModels;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/EditClonePathDialog.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/EditClonePathDialog.xaml.cs
index 4d532ba146..9bfea8f2dd 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/EditClonePathDialog.xaml.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/EditClonePathDialog.xaml.cs
@@ -13,7 +13,6 @@
using DevHome.SetupFlow.ViewModels;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Controls.Primitives;
namespace DevHome.SetupFlow.Views;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/PackageView.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/PackageView.xaml.cs
index f2b53c0655..f2804806ab 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/PackageView.xaml.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/PackageView.xaml.cs
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using DevHome.SetupFlow.ViewModels;
-using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace DevHome.SetupFlow.Views;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SetupTargetReviewView.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/SetupTargetReviewView.xaml.cs
index a0f9dfa6fa..34ab767485 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/SetupTargetReviewView.xaml.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SetupTargetReviewView.xaml.cs
@@ -1,10 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using DevHome.SetupFlow.ViewModels;
using Microsoft.UI.Xaml.Controls;
From 06753b41bdb78613dbfae22aeecc1f273498ab2a Mon Sep 17 00:00:00 2001
From: Branden Bonaby <105318831+bbonaby@users.noreply.github.com>
Date: Fri, 22 Mar 2024 11:58:35 -0700
Subject: [PATCH 020/121] [Dev Environments] Update experiments to enable
environments in Canary (#2452)
* add environments to canary
* update compute system service with same class Id in multiple packages workaround
---
common/Services/ComputeSystemService.cs | 25 +++++++++++++++++++++++++
src/NavConfig.jsonc | 4 ++--
2 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/common/Services/ComputeSystemService.cs b/common/Services/ComputeSystemService.cs
index c88c1c6a89..d69ef8ace3 100644
--- a/common/Services/ComputeSystemService.cs
+++ b/common/Services/ComputeSystemService.cs
@@ -10,11 +10,25 @@
using DevHome.Common.Models;
using DevHome.Logging;
using Microsoft.Windows.DevHome.SDK;
+using Windows.ApplicationModel;
namespace DevHome.Common.Services;
public class ComputeSystemService : IComputeSystemService
{
+ private const string DevHomePreviewPackageFamilyName = "Microsoft.Windows.DevHome_8wekyb3d8bbwe";
+
+ private const string DevHomeDevPackageFamilyName = "Microsoft.Windows.DevHome.Dev_8wekyb3d8bbwe";
+
+ private const string DevHomeCanaryPackageFamilyName = "Microsoft.Windows.DevHome.Canary_8wekyb3d8bbwe";
+
+ private readonly HashSet _devHomePackageFamilyName = new()
+ {
+ DevHomePreviewPackageFamilyName,
+ DevHomeDevPackageFamilyName,
+ DevHomeCanaryPackageFamilyName,
+ };
+
private readonly IExtensionService _extensionService;
private readonly IAccountsService _accountService;
@@ -33,6 +47,17 @@ public async Task> GetComputeSystemProvidersA
{
try
{
+ // Work around for issue where the Dev Home's extension service uses classIds within a package to identify the extension, but doesn't handle
+ // multiple packages with the same extension classIds. We need to filter out the Dev Home extensions that are not within the current package.
+ // E.g the Hyper-V extension is in Dev Home Dev, Canary and preview builds, each with the same class Id.
+ // So Dev Home sees this as 3 separate extensions, causing us to query the same COM server up to 3 times depending on how many of the 3 are
+ // installed.
+ if (_devHomePackageFamilyName.Contains(extension.PackageFamilyName) &&
+ extension.PackageFamilyName != Package.Current.Id.FamilyName)
+ {
+ continue;
+ }
+
var computeSystemProviders = await extension.GetListOfProvidersAsync();
var extensionObj = extension.GetExtensionObject();
var devIdList = new List();
diff --git a/src/NavConfig.jsonc b/src/NavConfig.jsonc
index d4c327017f..8c4c6f7ba8 100644
--- a/src/NavConfig.jsonc
+++ b/src/NavConfig.jsonc
@@ -50,8 +50,8 @@
},
{
"buildType": "canary",
- "enabledByDefault": false,
- "visible": false
+ "enabledByDefault": true,
+ "visible": true
},
{
"buildType": "release",
From 01ba562bf1bb1dd2c468f5e6f9e46a20e2e377eb Mon Sep 17 00:00:00 2001
From: Nick Eubanks
Date: Fri, 22 Mar 2024 16:27:25 -0400
Subject: [PATCH 021/121] Introducing Windows Customization (#2383)
---
DevHome.sln | 22 ++
common/DevHome.Common.csproj | 2 +-
docs/architecture.md | 1 +
src/App.xaml.cs | 4 +
src/DevHome.csproj | 3 +-
src/NavConfig.jsonc | 7 +
src/Services/PageService.cs | 2 +
src/Styles/TextBlock.xaml | 13 +-
.../DevHome.Customization/Customization.md | 36 ++++
.../DevHome.Customization.csproj | 56 +++++
.../Extensions/PageExtensions.cs | 16 ++
.../Extensions/ServiceExtensions.cs | 23 +++
.../Models/DeveloperFileExplorerSettings.cs | 105 ++++++++++
.../DevHome.Customization/NativeMethods.txt | 3 +
.../Strings/en-us/Resources.resw | 192 ++++++++++++++++++
.../TelemetryEvents/SettingChangedEvent.cs | 42 ++++
.../DeveloperFileExplorerViewModel.cs | 79 +++++++
.../ViewModels/MainPageViewModel.cs | 36 ++++
.../Views/DeveloperFileExplorerPage.xaml | 23 +++
.../Views/DeveloperFileExplorerPage.xaml.cs | 23 +++
.../Views/DeveloperFileExplorerView.xaml | 29 +++
.../Views/DeveloperFileExplorerView.xaml.cs | 24 +++
.../DevHome.Customization/Views/MainPage.cs | 25 +++
.../DevHome.Customization/Views/MainPage.xaml | 27 +++
.../Views/MainPageView.cs | 24 +++
.../Views/MainPageView.xaml | 35 ++++
...BackgroundProcesses.ElevatedServer.vcxproj | 4 +-
.../packages.config | 2 +-
...me.QuietBackgroundProcesses.Server.vcxproj | 4 +-
.../packages.config | 2 +-
30 files changed, 854 insertions(+), 10 deletions(-)
create mode 100644 tools/Customization/DevHome.Customization/Customization.md
create mode 100644 tools/Customization/DevHome.Customization/DevHome.Customization.csproj
create mode 100644 tools/Customization/DevHome.Customization/Extensions/PageExtensions.cs
create mode 100644 tools/Customization/DevHome.Customization/Extensions/ServiceExtensions.cs
create mode 100644 tools/Customization/DevHome.Customization/Models/DeveloperFileExplorerSettings.cs
create mode 100644 tools/Customization/DevHome.Customization/NativeMethods.txt
create mode 100644 tools/Customization/DevHome.Customization/Strings/en-us/Resources.resw
create mode 100644 tools/Customization/DevHome.Customization/TelemetryEvents/SettingChangedEvent.cs
create mode 100644 tools/Customization/DevHome.Customization/ViewModels/DeveloperFileExplorerViewModel.cs
create mode 100644 tools/Customization/DevHome.Customization/ViewModels/MainPageViewModel.cs
create mode 100644 tools/Customization/DevHome.Customization/Views/DeveloperFileExplorerPage.xaml
create mode 100644 tools/Customization/DevHome.Customization/Views/DeveloperFileExplorerPage.xaml.cs
create mode 100644 tools/Customization/DevHome.Customization/Views/DeveloperFileExplorerView.xaml
create mode 100644 tools/Customization/DevHome.Customization/Views/DeveloperFileExplorerView.xaml.cs
create mode 100644 tools/Customization/DevHome.Customization/Views/MainPage.cs
create mode 100644 tools/Customization/DevHome.Customization/Views/MainPage.xaml
create mode 100644 tools/Customization/DevHome.Customization/Views/MainPageView.cs
create mode 100644 tools/Customization/DevHome.Customization/Views/MainPageView.xaml
diff --git a/DevHome.sln b/DevHome.sln
index 87ee93969b..4b64753957 100644
--- a/DevHome.sln
+++ b/DevHome.sln
@@ -125,6 +125,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevSetupAgent.Test", "Hyper
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HyperVExtension.HostGuestCommunication", "HyperVExtension\src\HyperVExtension.HostGuestCommunication\HyperVExtension.HostGuestCommunication.csproj", "{D759CD66-494C-4A00-8075-8B65A9891349}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Customization", "Customization", "{623998FD-B0A6-4980-95D5-A5072301CA10}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.Customization", "tools\Customization\DevHome.Customization\DevHome.Customization.csproj", "{AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -769,6 +773,22 @@ Global
{D759CD66-494C-4A00-8075-8B65A9891349}.Release|x64.Build.0 = Release|x64
{D759CD66-494C-4A00-8075-8B65A9891349}.Release|x86.ActiveCfg = Release|x86
{D759CD66-494C-4A00-8075-8B65A9891349}.Release|x86.Build.0 = Release|x86
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug|Any CPU.ActiveCfg = Debug|x64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug|Any CPU.Build.0 = Debug|x64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug|arm64.ActiveCfg = Debug|arm64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug|arm64.Build.0 = Debug|arm64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug|x64.ActiveCfg = Debug|x64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug|x64.Build.0 = Debug|x64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug|x86.ActiveCfg = Debug|x86
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug|x86.Build.0 = Debug|x86
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Release|Any CPU.ActiveCfg = Release|x64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Release|Any CPU.Build.0 = Release|x64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Release|arm64.ActiveCfg = Release|arm64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Release|arm64.Build.0 = Release|arm64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Release|x64.ActiveCfg = Release|x64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Release|x64.Build.0 = Release|x64
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Release|x86.ActiveCfg = Release|x86
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -816,6 +836,8 @@ Global
{F4095FD3-6A3F-490B-966D-E63059612EE6} = {3E3791DF-070D-4ADE-96E8-93D6FBD53953}
{0E05A442-BDC7-43D4-A000-F8C986826716} = {3E3791DF-070D-4ADE-96E8-93D6FBD53953}
{D759CD66-494C-4A00-8075-8B65A9891349} = {81AACED5-CFB5-47A6-AFD6-4625AADCFFA3}
+ {623998FD-B0A6-4980-95D5-A5072301CA10} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD}
+ {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C} = {623998FD-B0A6-4980-95D5-A5072301CA10}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {030B5641-B206-46BB-BF71-36FF009088FA}
diff --git a/common/DevHome.Common.csproj b/common/DevHome.Common.csproj
index 1c3d3b33dd..5d1019e5aa 100644
--- a/common/DevHome.Common.csproj
+++ b/common/DevHome.Common.csproj
@@ -34,7 +34,7 @@
-
+
diff --git a/docs/architecture.md b/docs/architecture.md
index fa3a4126e0..f228426245 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -69,6 +69,7 @@ Dev Home currently has the following tools:
- [Dashboard](./tools.md#dashboard-tool)
- [Setup flow](./tools.md#setup-flow-tool)
- Extensions
+- [Windows customization](../tools/Customization/DevHome.Customization/Customization.md)
## Extensions
diff --git a/src/App.xaml.cs b/src/App.xaml.cs
index a7728c2d1a..4712ca8b93 100644
--- a/src/App.xaml.cs
+++ b/src/App.xaml.cs
@@ -9,6 +9,7 @@
using DevHome.Common.Models;
using DevHome.Common.Services;
using DevHome.Contracts.Services;
+using DevHome.Customization.Extensions;
using DevHome.Dashboard.Extensions;
using DevHome.ExtensionLibrary.Extensions;
using DevHome.Helpers;
@@ -141,6 +142,9 @@ public App()
// Environments
services.AddEnvironments(context);
+
+ // Windows customization
+ services.AddWindowsCustomization(context);
}).
Build();
diff --git a/src/DevHome.csproj b/src/DevHome.csproj
index 77c167e1f9..8328b70da1 100644
--- a/src/DevHome.csproj
+++ b/src/DevHome.csproj
@@ -61,7 +61,7 @@
-
+
all
@@ -85,6 +85,7 @@
+
diff --git a/src/NavConfig.jsonc b/src/NavConfig.jsonc
index 8c4c6f7ba8..8f22e75b68 100644
--- a/src/NavConfig.jsonc
+++ b/src/NavConfig.jsonc
@@ -33,6 +33,13 @@
"viewModelFullName": "DevHome.QuietBackgroundProcesses.UI.ViewModels.QuietBackgroundProcessesViewModel",
"icon": "f5b0",
"experimentalFeatureIdentity": "QuietBackgroundProcessesExperiment"
+ },
+ {
+ "identity": "DevHome.Customization",
+ "assembly": "DevHome.Customization",
+ "viewFullName": "DevHome.Customization.Views.MainPage",
+ "viewModelFullName": "DevHome.Customization.ViewModels.MainPageViewModel",
+ "icon": "e9f5"
}
]
}
diff --git a/src/Services/PageService.cs b/src/Services/PageService.cs
index e37fa384b9..0b11e2b5aa 100644
--- a/src/Services/PageService.cs
+++ b/src/Services/PageService.cs
@@ -5,6 +5,7 @@
using DevHome.Common.Contracts;
using DevHome.Common.Models;
using DevHome.Common.Services;
+using DevHome.Customization.Extensions;
using DevHome.ExtensionLibrary.Extensions;
using DevHome.Settings.Extensions;
using DevHome.ViewModels;
@@ -45,6 +46,7 @@ where assembly.GetName().Name == tool.Assembly
Configure();
this.ConfigureExtensionLibraryPages();
this.ConfigureSettingsPages();
+ this.ConfigureCustomizationPages();
// Configure Experimental Feature pages
ExperimentalFeature.LocalSettingsService = localSettingsService;
diff --git a/src/Styles/TextBlock.xaml b/src/Styles/TextBlock.xaml
index 50450a4e6d..99a6b16909 100644
--- a/src/Styles/TextBlock.xaml
+++ b/src/Styles/TextBlock.xaml
@@ -26,13 +26,22 @@
+
+
@@ -228,7 +228,7 @@
-
+ 0, 1, 0, 2
@@ -119,7 +120,7 @@
-
+
@@ -197,7 +198,8 @@
-
+
+
@@ -205,7 +207,7 @@
HorizontalAlignment="Stretch"
Padding="0,15,0,30"
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
- BorderThickness="{ThemeResource TopNavigationViewContentGridBorderThickness}">
+ BorderThickness="{ThemeResource TopLeftQuadrantThickness}">
@@ -259,7 +261,7 @@
HorizontalAlignment="Stretch"
Padding="0,15,0,30"
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
- BorderThickness="{ThemeResource TopNavigationViewContentGridBorderThickness}">
+ BorderThickness="{ThemeResource TopLeftQuadrantThickness}">
@@ -267,6 +269,7 @@
+
+ Grid.Column="1"
+ Visibility="{x:Bind ViewModel.RepositoriesCloned, Converter={StaticResource CollectionVisibilityConverter}}">
@@ -314,7 +317,18 @@
Margin="0, 50, 0, 0"/>
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs
index eff984525f..c89feb8d8e 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/Views/SummaryView.xaml.cs
@@ -9,7 +9,7 @@
namespace DevHome.SetupFlow.Views;
public sealed partial class SummaryView : UserControl
-{
+{
public SummaryView()
{
this.InitializeComponent();
From 560919a85d8c9325be859a1ed496a8663c656516 Mon Sep 17 00:00:00 2001
From: Huzaifa Danish
Date: Mon, 1 Apr 2024 09:34:41 -0700
Subject: [PATCH 040/121] Environments: Adding error handling UI (#2479)
* Added InfoBar; Rebased
---------
Co-authored-by: Huzaifa Danish
---
common/Contracts/IWindowsIdentityService.cs | 4 +-
common/DevHome.Common.csproj | 3 +-
common/Services/NotificationService.cs | 242 ++++++++++++++++++
common/Services/ToastNotificationService.cs | 73 ------
common/Services/WindowsIdentityService.cs | 5 +
common/Strings/en-us/Resources.resw | 26 +-
src/App.xaml.cs | 4 +-
.../DevHome.Environments.csproj | 1 +
.../Extensions/ServiceExtensions.cs | 1 -
.../ViewModels/LandingPageViewModel.cs | 43 +++-
.../Views/LandingPage.xaml | 15 +-
.../Views/LandingPage.xaml.cs | 1 +
.../ViewModels/SetupTargetViewModel.cs | 4 +-
13 files changed, 324 insertions(+), 98 deletions(-)
create mode 100644 common/Services/NotificationService.cs
delete mode 100644 common/Services/ToastNotificationService.cs
diff --git a/common/Contracts/IWindowsIdentityService.cs b/common/Contracts/IWindowsIdentityService.cs
index 309c698dd4..568b0660ba 100644
--- a/common/Contracts/IWindowsIdentityService.cs
+++ b/common/Contracts/IWindowsIdentityService.cs
@@ -5,5 +5,7 @@ namespace DevHome.Common.Contracts;
public interface IWindowsIdentityService
{
- public bool IsUserHyperVAdmin();
+ string? GetCurrentUserName();
+
+ bool IsUserHyperVAdmin();
}
diff --git a/common/DevHome.Common.csproj b/common/DevHome.Common.csproj
index c8f9a02568..b8a11d093f 100644
--- a/common/DevHome.Common.csproj
+++ b/common/DevHome.Common.csproj
@@ -23,6 +23,7 @@
+
@@ -36,7 +37,7 @@
-
+
diff --git a/common/Services/NotificationService.cs b/common/Services/NotificationService.cs
new file mode 100644
index 0000000000..e1ff0d315f
--- /dev/null
+++ b/common/Services/NotificationService.cs
@@ -0,0 +1,242 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using CommunityToolkit.Mvvm.Input;
+using CommunityToolkit.WinUI;
+using CommunityToolkit.WinUI.Behaviors;
+using DevHome.Common.Contracts;
+using DevHome.Common.Environments.Helpers;
+using Microsoft.UI.Xaml.Controls;
+using Microsoft.Windows.AppLifecycle;
+using Microsoft.Windows.AppNotifications;
+using Microsoft.Windows.AppNotifications.Builder;
+using Serilog;
+using Windows.ApplicationModel.Activation;
+
+namespace DevHome.Common.Services;
+
+public class NotificationService
+{
+ private readonly ILogger _log = Log.ForContext("SourceContext", nameof(NotificationService));
+
+ private readonly IWindowsIdentityService _windowsIdentityService;
+
+ private readonly string _componentName = "NotificationService";
+
+ private readonly string _hyperVText = "Hyper-V";
+
+ private readonly string _microsoftText = "Microsoft";
+
+ private readonly StringResource _stringResource;
+
+ private readonly Microsoft.UI.Dispatching.DispatcherQueue _dispatcher;
+
+ private StackedNotificationsBehavior? _notificationQueue;
+
+ public NotificationService(IWindowsIdentityService windowsIdentityService)
+ {
+ _windowsIdentityService = windowsIdentityService;
+ _dispatcher = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
+ _stringResource = new StringResource("DevHome.Common.pri", "DevHome.Common/Resources");
+ }
+
+ public bool ShowHyperVAdminWarningToast()
+ {
+ // Temporary toast notification to inform the user that they are not in the Hyper-V admin group.
+ // In the future we'll use an admin process from Dev Home to add the user to the group.
+ var toast = new AppNotificationBuilder()
+ .AddText("Warning")
+ .AddText(StringResourceHelper.GetResource(StringResourceHelper.UserNotInHyperAdminGroupMessage))
+ .AddButton(new AppNotificationButton(StringResourceHelper.GetResource(StringResourceHelper.UserNotInHyperAdminGroupButton))
+ .AddArgument("action", "AddUserToHyperVAdminGroup"))
+ .BuildNotification();
+
+ AppNotificationManager.Default.Show(toast);
+ return toast.Id != 0;
+ }
+
+ public void Initialize(StackedNotificationsBehavior notificationQueue)
+ {
+ _notificationQueue = notificationQueue;
+ }
+
+ public void HandlerNotificationActions(AppActivationArguments args)
+ {
+ if (args.Data is ToastNotificationActivatedEventArgs toastArgs)
+ {
+ try
+ {
+ if (toastArgs.Argument.Contains("action=AddUserToHyperVAdminGroup"))
+ {
+ // Launch compmgmt.msc in powershell
+ var psi = new ProcessStartInfo();
+ psi.FileName = "powershell";
+ psi.Arguments = "Start-Process compmgmt.msc -Verb RunAs";
+ Process.Start(psi);
+ }
+ }
+ catch (Exception ex)
+ {
+ _log.Error(_componentName, $"Unable to launch computer management due to exception", ex);
+ }
+ }
+ }
+
+ public void ShowRestartNotification()
+ {
+ if (_notificationQueue != null)
+ {
+ var command = new RelayCommand(() =>
+ {
+ var startInfo = new System.Diagnostics.ProcessStartInfo();
+ startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
+
+ // Restart the computer
+ startInfo.FileName = Environment.SystemDirectory + "\\shutdown.exe";
+ startInfo.Arguments = "-r -t 0";
+ startInfo.Verb = string.Empty;
+
+ var process = new System.Diagnostics.Process();
+ process.StartInfo = startInfo;
+ process.Start();
+ });
+
+ _dispatcher.EnqueueAsync(() =>
+ _notificationQueue?.Show(new Notification
+ {
+ Title = _stringResource.GetLocalized("HyperVErrorTitle", _microsoftText, _hyperVText),
+ Message = _stringResource.GetLocalized("RestartMessage", _hyperVText),
+ Severity = InfoBarSeverity.Warning,
+ ActionButton = new Button
+ {
+ Content = _stringResource.GetLocalized("RestartButton"),
+ Command = command,
+ },
+ }));
+ }
+ else
+ {
+ _log.Error(_componentName, "Notification queue is not initialized");
+ }
+ }
+
+ private void ShowUnableToAddToHyperVAdminGroupNotification()
+ {
+ ShowNotificationAsync(
+ _stringResource.GetLocalized("HyperVErrorTitle", _microsoftText, _hyperVText),
+ _stringResource.GetLocalized("UserAddHyperVAdminFailed", _hyperVText),
+ InfoBarSeverity.Warning).Wait();
+ }
+
+ public void CheckIfUserIsAHyperVAdminAndShowNotification()
+ {
+ if (!_windowsIdentityService.IsUserHyperVAdmin())
+ {
+ if (_notificationQueue != null)
+ {
+ var notification = new Notification();
+
+ var command = new RelayCommand(() =>
+ {
+ var user = _windowsIdentityService.GetCurrentUserName();
+ if (user == null)
+ {
+ _log.Error(_componentName, "Unable to get the current user name");
+ return;
+ }
+
+ var startInfo = new System.Diagnostics.ProcessStartInfo();
+ startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
+ startInfo.FileName = Environment.SystemDirectory + "\\net.exe";
+
+ // Add the user to the Hyper-V Administrators group
+ startInfo.Arguments = "localgroup \"Hyper-V Administrators\" " + user + " /add";
+ startInfo.UseShellExecute = true;
+ startInfo.Verb = "runas";
+
+ var process = new System.Diagnostics.Process();
+ process.StartInfo = startInfo;
+
+ // Since a UAC prompt will be shown, we need to wait for the process to exit
+ // This can also be cancelled by the user which will result in an exception
+ try
+ {
+ process.Start();
+ process.WaitForExit();
+
+ CloseNotification(notification);
+
+ if (process.ExitCode == 0)
+ {
+ ShowRestartNotification();
+ }
+ else
+ {
+ ShowUnableToAddToHyperVAdminGroupNotification();
+ }
+ }
+ catch (Exception ex)
+ {
+ _log.Error(_componentName, "Unable to add the user to the Hyper-V Administrators group", ex);
+ ShowUnableToAddToHyperVAdminGroupNotification();
+ }
+ });
+
+ _dispatcher.EnqueueAsync(() =>
+ {
+ notification = new Notification
+ {
+ Title = _stringResource.GetLocalized("HyperVErrorTitle", _microsoftText, _hyperVText),
+ Message = _stringResource.GetLocalized("UserNotInHyperAdminGroupMessage", _hyperVText),
+ Severity = InfoBarSeverity.Error,
+ ActionButton = new Button
+ {
+ Content = _stringResource.GetLocalized("HyperVAdminAddUser", _hyperVText),
+ Command = command,
+ },
+ };
+
+ _notificationQueue?.Show(notification);
+ });
+ }
+ else
+ {
+ _log.Error(_componentName, "Notification queue is not initialized");
+ }
+ }
+ }
+
+ public void CloseNotification(Notification notification)
+ {
+ _dispatcher.EnqueueAsync(() => _notificationQueue?.Remove(notification));
+ }
+
+ public async Task ShowNotificationAsync(string title, string message, InfoBarSeverity severity)
+ {
+ await _dispatcher.EnqueueAsync(() =>
+ {
+ var notification = new Notification
+ {
+ Title = title,
+ Message = message,
+ Severity = severity,
+ };
+
+ _notificationQueue?.Show(notification);
+ });
+ }
+
+ public void CheckIfUserIsAHyperVAdmin()
+ {
+ if (!_windowsIdentityService.IsUserHyperVAdmin())
+ {
+ ShowHyperVAdminWarningToast();
+ }
+ }
+}
diff --git a/common/Services/ToastNotificationService.cs b/common/Services/ToastNotificationService.cs
deleted file mode 100644
index 5c6631c66f..0000000000
--- a/common/Services/ToastNotificationService.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-using System;
-using System.Diagnostics;
-using DevHome.Common.Contracts;
-using DevHome.Common.Environments.Helpers;
-using Microsoft.Windows.AppLifecycle;
-using Microsoft.Windows.AppNotifications;
-using Microsoft.Windows.AppNotifications.Builder;
-using Serilog;
-using Windows.ApplicationModel.Activation;
-
-namespace DevHome.Common.Services;
-
-public class ToastNotificationService
-{
- private readonly ILogger _log = Log.ForContext("SourceContext", nameof(ToastNotificationService));
-
- private readonly IWindowsIdentityService _windowsIdentityService;
-
- public bool WasHyperVAddToAdminGroupSuccessful { get; private set; }
-
- public ToastNotificationService(IWindowsIdentityService windowsIdentityService)
- {
- _windowsIdentityService = windowsIdentityService;
- }
-
- public bool ShowHyperVAdminWarningToast()
- {
- // Temporary toast notification to inform the user that they are not in the Hyper-V admin group.
- // In the future we'll use an admin process from Dev Home to add the user to the group.
- var toast = new AppNotificationBuilder()
- .AddText("Warning")
- .AddText(StringResourceHelper.GetResource(StringResourceHelper.UserNotInHyperAdminGroupMessage))
- .AddButton(new AppNotificationButton(StringResourceHelper.GetResource(StringResourceHelper.UserNotInHyperAdminGroupButton))
- .AddArgument("action", "AddUserToHyperVAdminGroup"))
- .BuildNotification();
-
- AppNotificationManager.Default.Show(toast);
- return toast.Id != 0;
- }
-
- public void HandlerNotificationActions(AppActivationArguments args)
- {
- if (args.Data is ToastNotificationActivatedEventArgs toastArgs)
- {
- try
- {
- if (toastArgs.Argument.Contains("action=AddUserToHyperVAdminGroup"))
- {
- // Launch compmgmt.msc in powershell
- var psi = new ProcessStartInfo();
- psi.FileName = "powershell";
- psi.Arguments = "Start-Process compmgmt.msc -Verb RunAs";
- Process.Start(psi);
- }
- }
- catch (Exception ex)
- {
- _log.Error($"Unable to launch computer management due to exception", ex);
- }
- }
- }
-
- public void CheckIfUserIsAHyperVAdmin()
- {
- if (!_windowsIdentityService.IsUserHyperVAdmin())
- {
- ShowHyperVAdminWarningToast();
- }
- }
-}
diff --git a/common/Services/WindowsIdentityService.cs b/common/Services/WindowsIdentityService.cs
index 5503a1e26d..0655fe9cfa 100644
--- a/common/Services/WindowsIdentityService.cs
+++ b/common/Services/WindowsIdentityService.cs
@@ -23,4 +23,9 @@ public bool IsUserHyperVAdmin()
var wasHyperVSidFound = _currentUserIdentity?.Groups?.Any(sid => sid.Value == HyperVAdminSid);
return wasHyperVSidFound ?? false;
}
+
+ public string? GetCurrentUserName()
+ {
+ return _currentUserIdentity?.Name;
+ }
}
diff --git a/common/Strings/en-us/Resources.resw b/common/Strings/en-us/Resources.resw
index 4605c949b2..1873f71307 100644
--- a/common/Strings/en-us/Resources.resw
+++ b/common/Strings/en-us/Resources.resw
@@ -205,12 +205,32 @@
Uptime:
Title for the uptime property of a compute system. (The amount of time its been running)
+
+ Add user to {0} administrators group
+ Locked="{0}" Text for the button to add user to {0} administrators group
+
+
+ {0} {1}
+ {Locked="{0}","{1}"} Title text for the UI showing errors for user not part of {1} administrators group
+
+
+ Restart now
+ Locked="{0}" Text for button that restarts the system.
+
+
+ You must restart the computer after adding the user to the {0} administrators group for changes to take effect.
+ Locked="{0}" Text explaining that a restart is needed after a user is added to the {0} group.
+
+
+ Unable to add user to {0} administrators group. Please try manually.
+ Locked="{0}" Text explaining that the user add operation to {0} administrators group failed.
+
Launch computer management
- Button text for the user to click, in order for us to add them to the Hyper-V admin group
+ Button text for the user to click, in order to launch computer management
- The current user is not a Hyper-V administrator. Hyper-V Virtual machines will not load. Please add the user to the Hyper-V Administrators group and reboot.
- Text explaining that the user is not in the hyper-v admin group and that we need to add them.
+ The current user is not a {0} administrators. {0} virtual machines will not load. Please add the user to the {0} administrators group and reboot.
+ Locked="{0}" Text explaining that the user is not in the {0} administrators group and that we need to add them.
\ No newline at end of file
diff --git a/src/App.xaml.cs b/src/App.xaml.cs
index 43b4891fc2..3561e1d163 100644
--- a/src/App.xaml.cs
+++ b/src/App.xaml.cs
@@ -126,7 +126,7 @@ public App()
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
- services.AddSingleton();
+ services.AddTransient();
// Core Services
services.AddSingleton();
@@ -206,7 +206,7 @@ private async void OnActivated(object? sender, AppActivationArguments args)
{
if (args.Kind == ExtendedActivationKind.ToastNotification)
{
- GetService().HandlerNotificationActions(args);
+ GetService().HandlerNotificationActions(args);
return;
}
diff --git a/tools/Environments/DevHome.Environments/DevHome.Environments.csproj b/tools/Environments/DevHome.Environments/DevHome.Environments.csproj
index 5e87fa377f..a544784293 100644
--- a/tools/Environments/DevHome.Environments/DevHome.Environments.csproj
+++ b/tools/Environments/DevHome.Environments/DevHome.Environments.csproj
@@ -9,6 +9,7 @@
+
diff --git a/tools/Environments/DevHome.Environments/Extensions/ServiceExtensions.cs b/tools/Environments/DevHome.Environments/Extensions/ServiceExtensions.cs
index 31d498c05d..8216429031 100644
--- a/tools/Environments/DevHome.Environments/Extensions/ServiceExtensions.cs
+++ b/tools/Environments/DevHome.Environments/Extensions/ServiceExtensions.cs
@@ -21,7 +21,6 @@ public static IServiceCollection AddEnvironments(this IServiceCollection service
// Services
services.AddSingleton();
- services.AddSingleton();
services.AddSingleton();
#if DEBUG
diff --git a/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs b/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs
index 3b88ddbae0..f3d7b12e40 100644
--- a/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs
+++ b/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs
@@ -9,12 +9,19 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.WinUI;
+using CommunityToolkit.WinUI.Behaviors;
using CommunityToolkit.WinUI.Collections;
+using DevHome.Common.Environments.Helpers;
using DevHome.Common.Environments.Models;
using DevHome.Common.Environments.Services;
+using DevHome.Common.Extensions;
+using DevHome.Common.Helpers;
using DevHome.Common.Services;
using DevHome.Environments.Helpers;
+using Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
using Serilog;
+using WinUIEx;
namespace DevHome.Environments.ViewModels;
@@ -29,7 +36,7 @@ public partial class LandingPageViewModel : ObservableObject, IDisposable
private readonly EnvironmentsExtensionsService _extensionsService;
- private readonly ToastNotificationService _notificationService;
+ private readonly NotificationService _notificationService;
private readonly IComputeSystemManager _computeSystemManager;
@@ -64,11 +71,11 @@ public partial class LandingPageViewModel : ObservableObject, IDisposable
public LandingPageViewModel(
IComputeSystemManager manager,
EnvironmentsExtensionsService extensionsService,
- ToastNotificationService toastNotificationService)
+ NotificationService notificationService)
{
_dispatcher = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
_extensionsService = extensionsService;
- _notificationService = toastNotificationService;
+ _notificationService = notificationService;
_computeSystemManager = manager;
_stringResource = new StringResource("DevHome.Environments.pri", "DevHome.Environments/Resources");
@@ -79,13 +86,17 @@ public LandingPageViewModel(
ComputeSystemsView = new AdvancedCollectionView(ComputeSystems);
}
+ public void Initialize(StackedNotificationsBehavior notificationQueue)
+ {
+ _notificationService.Initialize(notificationQueue);
+
+ // To Do: Need to give the users a way to disable this, if they don't want to use Hyper-V
+ _ = Task.Run(() => _notificationService.CheckIfUserIsAHyperVAdminAndShowNotification());
+ }
+
[RelayCommand]
public async Task SyncButton()
{
- // temporary, we'll need to give the users a way to disable this.
- // if they don't want to use hyper-v
- _notificationService.CheckIfUserIsAHyperVAdmin();
-
// Reset the sort and filter
SelectedSortIndex = -1;
Providers = new ObservableCollection { _stringResource.GetLocalized("AllProviders") };
@@ -172,9 +183,6 @@ public async Task LoadModelAsync(bool useDebugValues = false)
await RunSyncTimmer();
});
- // temporary, we'll need to give the users a way to disable this.
- // if they don't want to use hyper-v
- _notificationService.CheckIfUserIsAHyperVAdmin();
for (var i = ComputeSystems.Count - 1; i >= 0; i--)
{
ComputeSystems[i].RemoveStateChangedHandler();
@@ -195,6 +203,17 @@ private async Task AddAllComputeSystemsFromAProvider(ComputeSystemsLoadedData da
{
var provider = data.ProviderDetails.ComputeSystemProvider;
+ // Show error notifications for failed provider/developer id combinations
+ foreach (var mapping in data.DevIdToComputeSystemMap.Where(kv =>
+ kv.Value.Result.Status == Microsoft.Windows.DevHome.SDK.ProviderOperationStatus.Failure))
+ {
+ var result = mapping.Value.Result;
+ await _notificationService.ShowNotificationAsync(provider.DisplayName, result.DisplayMessage, InfoBarSeverity.Error);
+
+ _log.Error($"Error occurred while adding Compute systems to environments page for provider: {provider.Id}", result.DiagnosticText, result.ExtendedError);
+ data.DevIdToComputeSystemMap.Remove(mapping.Key);
+ }
+
await _dispatcher.EnqueueAsync(async () =>
{
Providers.Add(provider.DisplayName);
@@ -204,8 +223,6 @@ await _dispatcher.EnqueueAsync(async () =>
// In the future when we support switching between accounts in the environments page, we will need to handle this differently.
// for now we'll show all the compute systems from a provider.
- var computeSystemResult = data.DevIdToComputeSystemMap.Values.FirstOrDefault();
-
if (computeSystemList == null || computeSystemList.Count == 0)
{
_log.Error($"No Compute systems found for provider: {provider.Id}");
@@ -222,7 +239,7 @@ await _dispatcher.EnqueueAsync(async () =>
}
catch (Exception ex)
{
- _log.Error($"Error occurred while adding Compute systems to environments page for provider: {provider.Id}", ex);
+ _log.Error($"Exception occurred while adding Compute systems to environments page for provider: {provider.Id}", ex);
}
});
}
diff --git a/tools/Environments/DevHome.Environments/Views/LandingPage.xaml b/tools/Environments/DevHome.Environments/Views/LandingPage.xaml
index 5b97553e50..4b545bab92 100644
--- a/tools/Environments/DevHome.Environments/Views/LandingPage.xaml
+++ b/tools/Environments/DevHome.Environments/Views/LandingPage.xaml
@@ -10,8 +10,9 @@
xmlns:commonModels="using:DevHome.Common.Environments.Models"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
+ xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
+ xmlns:winUIBehaviors="using:CommunityToolkit.WinUI.Behaviors"
behaviors:NavigationViewHeaderBehavior.HeaderMode="Never"
- xmlns:labs="using:CommunityToolkit.Labs.WinUI"
Loaded="OnLoaded">
@@ -164,7 +165,7 @@
-
+
@@ -237,5 +238,15 @@
+
+
+
+
+
+
diff --git a/tools/Environments/DevHome.Environments/Views/LandingPage.xaml.cs b/tools/Environments/DevHome.Environments/Views/LandingPage.xaml.cs
index bb107adae7..c814b30494 100644
--- a/tools/Environments/DevHome.Environments/Views/LandingPage.xaml.cs
+++ b/tools/Environments/DevHome.Environments/Views/LandingPage.xaml.cs
@@ -21,6 +21,7 @@ public LandingPage()
{
ViewModel = Application.Current.GetService();
InitializeComponent();
+ ViewModel.Initialize(NotificationQueue);
#if DEBUG
Loaded += AddDebugButtons;
diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs
index 357482d259..71842a11c3 100644
--- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs
+++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs
@@ -24,7 +24,7 @@ public partial class SetupTargetViewModel : SetupPageViewModelBase
private readonly Microsoft.UI.Dispatching.DispatcherQueue _dispatcher;
- private readonly ToastNotificationService _toastNotificationService;
+ private readonly NotificationService _toastNotificationService;
private const string SortByDisplayName = "DisplayName";
@@ -76,7 +76,7 @@ public SetupTargetViewModel(
SetupFlowOrchestrator orchestrator,
IComputeSystemManager computeSystemManager,
ComputeSystemViewModelFactory computeSystemViewModelFactory,
- ToastNotificationService toastNotificationService)
+ NotificationService toastNotificationService)
: base(stringResource, orchestrator)
{
// Setup initial state for page.
From 18999cbd9f944cee9f3aa15fc4ba67ee82d49aaf Mon Sep 17 00:00:00 2001
From: Nick Eubanks
Date: Mon, 1 Apr 2024 14:05:49 -0400
Subject: [PATCH 041/121] Add new Breadcrumb header to Customization (#2501)
---
.../ViewModels/DeveloperFileExplorerViewModel.cs | 16 ++++++++++++++--
.../ViewModels/MainPageViewModel.cs | 11 +++++++++--
.../Views/DeveloperFileExplorerPage.xaml | 6 ++----
.../DevHome.Customization/Views/MainPage.xaml | 6 ++----
4 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/tools/Customization/DevHome.Customization/ViewModels/DeveloperFileExplorerViewModel.cs b/tools/Customization/DevHome.Customization/ViewModels/DeveloperFileExplorerViewModel.cs
index d81cf18af7..b44e4166a9 100644
--- a/tools/Customization/DevHome.Customization/ViewModels/DeveloperFileExplorerViewModel.cs
+++ b/tools/Customization/DevHome.Customization/ViewModels/DeveloperFileExplorerViewModel.cs
@@ -1,7 +1,10 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
+using DevHome.Common.Models;
+using DevHome.Common.Services;
using DevHome.Customization.Models;
using DevHome.Customization.TelemetryEvents;
using Microsoft.Internal.Windows.DevHome.Helpers;
@@ -10,11 +13,20 @@ namespace DevHome.Customization.ViewModels;
public partial class DeveloperFileExplorerViewModel : ObservableObject
{
- private readonly ShellSettings _shellSettings;
+ private readonly ShellSettings _shellSettings;
+
+ public ObservableCollection Breadcrumbs { get; }
public DeveloperFileExplorerViewModel()
{
- _shellSettings = new ShellSettings();
+ _shellSettings = new ShellSettings();
+
+ var stringResource = new StringResource("DevHome.Customization.pri", "DevHome.Customization/Resources");
+ Breadcrumbs =
+ [
+ new(stringResource.GetLocalized("MainPage_Header"), typeof(MainPageViewModel).FullName!),
+ new(stringResource.GetLocalized("DeveloperFileExplorer_Header"), typeof(DeveloperFileExplorerViewModel).FullName!)
+ ];
}
public bool ShowFileExtensions
diff --git a/tools/Customization/DevHome.Customization/ViewModels/MainPageViewModel.cs b/tools/Customization/DevHome.Customization/ViewModels/MainPageViewModel.cs
index d639f7631f..75419499ae 100644
--- a/tools/Customization/DevHome.Customization/ViewModels/MainPageViewModel.cs
+++ b/tools/Customization/DevHome.Customization/ViewModels/MainPageViewModel.cs
@@ -2,10 +2,12 @@
// Licensed under the MIT License.
using System;
+using System.Collections.ObjectModel;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DevHome.Common.Extensions;
+using DevHome.Common.Models;
using DevHome.Common.Services;
using Microsoft.UI.Xaml;
using Windows.System;
@@ -14,12 +16,17 @@ namespace DevHome.Customization.ViewModels;
public partial class MainPageViewModel : ObservableObject
{
- private INavigationService NavigationService { get; }
+ private INavigationService NavigationService { get; }
+
+ public ObservableCollection Breadcrumbs { get; }
public MainPageViewModel(
INavigationService navigationService)
{
- NavigationService = navigationService;
+ NavigationService = navigationService;
+
+ var stringResource = new StringResource("DevHome.Customization.pri", "DevHome.Customization/Resources");
+ Breadcrumbs = [new(stringResource.GetLocalized("MainPage_Header"), typeof(MainPageViewModel).FullName!)];
}
[RelayCommand]
diff --git a/tools/Customization/DevHome.Customization/Views/DeveloperFileExplorerPage.xaml b/tools/Customization/DevHome.Customization/Views/DeveloperFileExplorerPage.xaml
index 88ba47cf03..26b408f760 100644
--- a/tools/Customization/DevHome.Customization/Views/DeveloperFileExplorerPage.xaml
+++ b/tools/Customization/DevHome.Customization/Views/DeveloperFileExplorerPage.xaml
@@ -3,11 +3,9 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="using:DevHome.Common.Behaviors"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:views="using:DevHome.Customization.Views"
- behaviors:NavigationViewHeaderBehavior.HeaderMode="Always"
- mc:Ignorable="d">
+ behaviors:NavigationViewHeaderBehavior.HeaderTemplate="{StaticResource BreadcrumbBarDataTemplate}"
+ behaviors:NavigationViewHeaderBehavior.HeaderContext="{x:Bind ViewModel}">
diff --git a/tools/Customization/DevHome.Customization/Views/MainPage.xaml b/tools/Customization/DevHome.Customization/Views/MainPage.xaml
index 189f2aeb26..70a9d76e23 100644
--- a/tools/Customization/DevHome.Customization/Views/MainPage.xaml
+++ b/tools/Customization/DevHome.Customization/Views/MainPage.xaml
@@ -6,12 +6,10 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="using:DevHome.Common.Behaviors"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pg="using:DevHome.Common"
xmlns:views="using:DevHome.Customization.Views"
- behaviors:NavigationViewHeaderBehavior.HeaderMode="Always"
- mc:Ignorable="d">
+ behaviors:NavigationViewHeaderBehavior.HeaderTemplate="{StaticResource BreadcrumbBarDataTemplate}"
+ behaviors:NavigationViewHeaderBehavior.HeaderContext="{x:Bind ViewModel}">
From f4e9a648bd2a65310628bee8214f505a5b2af267 Mon Sep 17 00:00:00 2001
From: Soham Das <93530301+SohamDas2021@users.noreply.github.com>
Date: Mon, 1 Apr 2024 13:48:49 -0700
Subject: [PATCH 042/121] Dev drive insights and pip cache move rebased to
changes from main (#2486)
* Applied Dev Drive Insights changes on top of Windows Customization from Main?
* Addressed PR comments 1
* Addressed PR comments
* Addressed PR comments
* More cleanups
---
DevHome.sln | 4 +
src/Assets/Fonts/AMCIcons.ttf | Bin 0 -> 75832 bytes
src/Styles/FontFamilies.xaml | 2 +
.../DevHome.Customization.csproj | 4 +
.../Extensions/PageExtensions.cs | 3 +-
.../Extensions/ServiceExtensions.cs | 7 +-
.../Strings/en-us/Resources.resw | 60 ++++
.../DevDriveInsights/DevDriveCardViewModel.cs | 57 ++++
.../DevDriveOptimizedCardViewModel.cs | 33 ++
.../DevDriveOptimizerCardViewModel.cs | 64 ++++
.../OptimizeDevDriveDialogViewModel.cs | 145 +++++++++
.../ViewModels/DevDriveInsightsViewModel.cs | 298 ++++++++++++++++++
.../ViewModels/MainPageViewModel.cs | 79 ++---
.../Views/DevDriveInsightsPage.xaml | 22 ++
.../Views/DevDriveInsightsPage.xaml.cs | 37 +++
.../Views/DevDriveInsightsView.xaml | 147 +++++++++
.../Views/DevDriveInsightsView.xaml.cs | 28 ++
.../Views/MainPageView.xaml | 12 +-
.../Views/OptimizeDevDriveDialog.xaml | 27 ++
.../Views/OptimizeDevDriveDialog.xaml.cs | 23 ++
.../DevHome.SetupFlow/Models/DevDrive.cs | 13 +
.../DevHome.SetupFlow/Models/IDevDrive.cs | 12 +
.../Services/DevDriveManager.cs | 7 +-
23 files changed, 1042 insertions(+), 42 deletions(-)
create mode 100644 src/Assets/Fonts/AMCIcons.ttf
create mode 100644 tools/Customization/DevHome.Customization/ViewModels/DevDriveInsights/DevDriveCardViewModel.cs
create mode 100644 tools/Customization/DevHome.Customization/ViewModels/DevDriveInsights/DevDriveOptimizedCardViewModel.cs
create mode 100644 tools/Customization/DevHome.Customization/ViewModels/DevDriveInsights/DevDriveOptimizerCardViewModel.cs
create mode 100644 tools/Customization/DevHome.Customization/ViewModels/DevDriveInsights/OptimizeDevDriveDialogViewModel.cs
create mode 100644 tools/Customization/DevHome.Customization/ViewModels/DevDriveInsightsViewModel.cs
create mode 100644 tools/Customization/DevHome.Customization/Views/DevDriveInsightsPage.xaml
create mode 100644 tools/Customization/DevHome.Customization/Views/DevDriveInsightsPage.xaml.cs
create mode 100644 tools/Customization/DevHome.Customization/Views/DevDriveInsightsView.xaml
create mode 100644 tools/Customization/DevHome.Customization/Views/DevDriveInsightsView.xaml.cs
create mode 100644 tools/Customization/DevHome.Customization/Views/OptimizeDevDriveDialog.xaml
create mode 100644 tools/Customization/DevHome.Customization/Views/OptimizeDevDriveDialog.xaml.cs
diff --git a/DevHome.sln b/DevHome.sln
index d3c0227078..8927567199 100644
--- a/DevHome.sln
+++ b/DevHome.sln
@@ -125,6 +125,10 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Customization", "Customization", "{623998FD-B0A6-4980-95D5-A5072301CA10}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.Customization", "tools\Customization\DevHome.Customization\DevHome.Customization.csproj", "{AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}"
+ ProjectSection(ProjectDependencies) = postProject
+ {0901B260-1B88-4B99-A9F8-477ED0A74FBD} = {0901B260-1B88-4B99-A9F8-477ED0A74FBD}
+ {54082587-A435-423F-AE1B-01B906FFA7C5} = {54082587-A435-423F-AE1B-01B906FFA7C5}
+ EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/Assets/Fonts/AMCIcons.ttf b/src/Assets/Fonts/AMCIcons.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..75e3b36421ce267692f884813cddefea27f33242
GIT binary patch
literal 75832
zcmdqK2YejW^*?%Nwnb+QPRcy(Y<=z`MxXQgZFl)dVjBQ$|ap<8F
z0|^iyAp#O0p(LROl3zjsK{jA&XqI;UzUR)&Y9-r0lHdD%-uu6&quuFuX6`-robM_3
zE)y7I=`6}rEHY_YX+`I^+bS3ny0CZA%#NPfdlp{0fiaB_pLfq$vv_^gzZR4*rpICJ
z2g?_4TF+9Ln+f?vRLb(zJC?28G_IL3^S4aUzrJGW;w44D`{b`U_7XldE3m^ZWIlrO
z)!5Ekv1ar3dppm59NTv@rrN%G-8qZ5eDU)*W5%P5iCJqFZ(lFigi$!2kMn(N7q40B
z`{8pxVuBatr9{@R+qC)Q&shZyr_*sp?;`wigX(;({jAK!ub4gsI~e<~zv=Iy<-0Ha
z>BW;LPsTG@3Z1EABJIT=wxlyN8IGUK$LqYJ~$>stgaUGW`6J*VDFu_o9zT%Nf!~#8SLZzE&=epNsQ(8GBAsF5RmSANhP0
zmKu3IQ3qcQzwVT}Vz@s(N*PL>3vxO9SVS&E-gmlp`tSA)E1&Llx{p#e)q%3EoR^Yx
z|B=UNJ82))r%2by`%a$3`c%9lw&}ySaa?&OzQlI&Gim0hFg4EQ`_7Y>S}f@!pQ~CV
z--mCbfAJ+2QGD>HT0~t=h_Vb86+nD{lqLVsMauapte!a%Tl@g4N0*G^Q^z}RR5{8!
zs>qLkL&b=QBeYMXZ(5h`g+2I-V*eh#A8Tw8i2m?k^am;VZOTbJIK5UXh_N&f2}2Tx
z=^%#Z&%n2VONmTI&z!|OyO9~OZUR9#f*7-a7_)*Hvw;}1gBae6-pmPN%mreQuWo#2
zgBZ&JG3Eg=<^?h412N_YF_sHrEC7OZ1u+%`F%|+b76vhv4`OT-h_M0?V}&5bia?AN
zgBU9TF;)s>$Q!K~(=}0kls&zDI)?YXC9U2x6=W
z#8@+ku@(^8gk&FU1u@nJVyqp+SO~N;
z7J?W%3#4$#VzwCTXM-3!2gKMC5MxV0j4cB(wj9LR3J_x}L5%f+7+VEmY&D3nH6X^;
zf*4x|Vr)H#u?--`Hi8)21Y&G6h_Njo#|79I=Ybg8
z4Pxwk5b=Bz-+MreT>xV2LJ(sYff(BhV(elNWBWjiT>@h4QV?VNL5y7nV(b8jv4bGS
z4uKfE9K_faAjYl)F?JP*v8zFh{Q$(+H6X^W1u=FVh_UNI(4HX1ZUiy*Ll9$!L5%$f
z#Mn(B#%=~Nb_utiMEWeG`D6`gR}KRWaK|3s$NUJMm-
z0Z!NP-j%_8?-}2l^WKs7Z+!p34-6l;K3Md@iVs%z3;pVTU4L4CM!&V+-JjE++n?88
z(qGkI*WcVfuD_>$TK~%a)&1-HH}-Gt-`2mY|HA&g{rmdw>c6M|;r=K4f7SnV|Iz+`
z^?%zxcvO8f^Jw-_|IxtFrlZ##z4ho_NAElOi}na9k>
z?8m&va*vfAYdtph*t}y4kF7hl<=D1kR~)HgNJb=#|?b6>X5&??fB;&;|wlmHoAeHdx-j
zDya=FNNR&8`ky*O8(f1nxKnO}=jApyA-93)m=$f{PiliT$JUQ%gZh874c4FyZvKzj
zz%rr@`VwuhVptnoEw@41ztslsoS_XCCE7rB@?R(ak@L%(9XWpYwb_2xZ(L8hwz}52
z);hILwexj=A4o3e3l8*uCuFk|GS>Nk^LFPgj$bveAv9-e5v_7^A7VC^E~rZbBDRu^o8l4<_^>EOb?juGR-$tno5j2
zjmE6!vbJW8fx-28<|mo=WZs;4P3HE@O_>`r$7hxq-pb52{KRmdVZEWzP+<@=;u%+F
zEXXhblHRPpP`^n(CoPutL0WI>Td9A*=NiD)mXu3V4s$8@y|PPKNT&$P@L7S++S6Yk
z%su`7;d_O;p>3f;S{KTceL{h0e*J
z0}pNlK3osHxEA>F$3Q-}0|`CF`hYf`Ccgu}D_I#tYXrSeE($8I>X^D!eT}AD^MbZs
zd$IOY-QQBeDc7cantE31pVKC!y{WI!-;jPkOqyE_8HQ^!&&hl;>mH-Qc#FwzdfIft
zyxRN+OTOhotJ8Y6O=o+=o@ZZak2xN4yyl$aywrKW^E1~x*K_Vk?q6gt&Au-Ch3vtc
zV9xZM3v=%GlzZOt`g~^JqyFjszvV8>eJaozxH|A;o+xVwifQBS9{0y_pN>D=T|Hq(PexCqXVb(>C)H1SYVw%L?@XCC
z<*BKYram?GyJ_y}#_4a(`0dQAW?eSx_-yO!mf6c^KRhQmcf-8gc~{K)a{eO=Rxi9`
z;kReqx5&BZip9FcI~RX(_KLGVKj-cx?=IcA^yy{2%Pq@qSaIcwf2>^Go8G&=_sFW%
zt8>>pxOV@#%ykpj{c!!9^;fTdX+!yjz75AVx;D<*^z7!c%})aEZ{G6UmVvG1TOZ!0
z-L`hyzHJX~AGiI@?I(BS@AzitxLw)1cJBJyxiii)pVzxvx4U%rljqMr|C{JDd)oJG
zzQBIL#TQyGYP#q*dwceN2-I^YW9o}ETY+(O=-)=aQR6rI)fWxss>a90i;rryp4hM1
z`hx*LUP3|96gtfgOR^qkS9nCL(P9t-{@fC=+E~>rR@!q7Vvdk1R9BUV0b@lob_?1-
zZdfo{JYuEx`Ie0{Dl2DfY&o$}S<{8bR(n)YRn${GHcab-w`Q75nS-~|wvN%s179d7
zs|~cqPtA_?i_UDi-~``RO^TgJO%=6+579n6Eo>Uy?{(+nS!a`NCFF*xjRrwyQ0WXp
zAUD(`)R=1WYK>Jjl@)fuBUmjuK`SI)#9v{vTC{jG1HB`j-H(@P66kDOjzBN1N)?PK
ziV8$I%|flF%R9;!@y)pA(hDMbhrw51-}Ic|c_!cMwTKaYnl;vE9h|PbiLlQV3c2D@
zdRTf>HKVnV%M~i0v9YyNcs$;D^#vc#&1)(Pq+TM_+*dfeNQ@SFgmjfI#ZuS3us&5^
z?A1OZl>POhG{NX8w8Va=&&l*yW52V;d8J8JMFmpvgS>cJi_(3gkkNj+&vm3RPDmR92)5HaoBK+)%hg;QuPs$TL-y;JIO^;T&zE
zO{uUEr>Ibpia3*)m6{DLtY)iUd+uiwLXElUHnTgZpY(SjO$h$rY9S<~{(Z7O=r%g_
zdb8eI;^_J5Z(d(L{;GXD${k@_y4~UmrBvS3_r|K;H~Vg?ObNLx_HzS#s`yv0Vpto$b-$tn9R`Y+u-2y8JCy;b^~qbfHUGYNLhIw)cdl
z#Q4BH#Dri
z@vN*YSIC%|)99|9-Q9nf)o2>2Kmy#$#L&uH$X{wDSxQW!J
zx~fnhS8KJ{Dl2NDvu7BC#GpRmYYs
zPRq&7Gr2=)sd{I6*|>6-t9)FU-lb1X3%jz6>AvRL;>O!gc
zEroVlQS&H0m8a^p7q;Z<&6zF~;qOO@_muw;E7DnyY8VoY1Vtgmik)G2^CHRZSZ=Hk@t*
zm!ziUE?&E_s&do1#eO_t{M@RIYZvFrFBKjuojXQ)m(;YtBAn~3E6Yn8e1x7=)t#1C
zR_9e@mGt-_Xb(VgXoPMlpWM!OdZ8i5)lM=)ztQp`zdsnQ^^(V=B6T}pmdbCOC^^mUjkW>V2Z`i=A>x~r`B
z1}f%_88vFmyb5iavZisD1T2<7sp|yeYq_OvF+!{$aFrr3I$fPOec)@lFlq^uxYf*6
zN|%|X1QZ4!aDdp+wUr(R9T8qWldS0x<}1M
z$iZPkS-CE02~U5NbfPW_^y7x#ycIs_X}}fh$d{T78XY2oVI1`hY*Ih)T>O
z$s#Lojy8#*H3<$@0Gc^jH;~$ah=JxI0RsgisS)s$T8uWYJkZl~U}baD@=LoX9a`NY
z?5aAetAKjHyxc+TdC7lRXsgd?O7ELhiOmol+B0k)Lt_2(q#<|%PyT5
zTi<=@@}~NwmrnUM)G@zW+*`R|Y(cnvesydYt;O5pG2Tm58QXsGuS;ol!qshUtH$T&
zkMC`7yQ+uw%)9s6-HRHj>*9|Gm!@FDA{s<>AUCf>gb*|}i+LRVaKuV)$9srhX0Z~e
zV1pX!RXyyDQ`oq@PresFap+L|#QRU|9Y-@YXh*?h$Awf%9rL!-XD!A$L9iQzm
z`rUvhuF%{==Tt|w+>QcJ*d3cAO`Gmq(fik(IE(uGP(KP%3@LaT`6T$c{lJBjz+2kS
zF}U!!0-x1~l(iF&!$gK^9pF$}6Covag71lv?J#uW05>@_QGNzpaiWjDReghe4{0-s
zb^@vTD3-)~EBLNOkRfFPL2~Iy!c#`7RPzZy3v+?21>x}YYd5rxUU}7QpMKHdKknM~
z$HR;CS+lNN7m2L9c9z(*azatbl(mtnjucHshHKV_ecj#rHq3HmWN1=)>YG;f6ctTa
z*(5~AZnFGgtx+$%A_M|p@bxlpRy>0UBB0ca>XyDEd6e#k6P-6&~N7ZJ!1Lpi}F<-B*
zojKa;9X+#FuMfL2v(h~c)kT?|ordC?h8(>aSU5HqKW>H$<1EiyX3?ulv4>m+gDYfD
z(E)MU^u98`(FiDK&2fePZnUNwoQAerf7Z8n(bJFI){2dEi^-j*)8))vzPfDP@m)JV
zU0b?l`P>|xE+jloEG2MO6lx6_HKPVxmRxsc_HLsoqj}?w{WE9o-?6bd!(?;?b*c9D
z36lc1Jow-(zA2MBEV|TSiMksPM`ocbWUeq|=>x6poLS$M$o^uVmeOG=8C
zo-@a155lrSbWgWKcQK;Hg~>gMKoN)TI^Zdx3b2YpF=~m5TC}9_bUvA#Rb%rVWmffx
zlB&wm0iCr><1=Lr=nO!%s0M@jyG+wgI!ALLe{7W}Jv}zsHMgpIjw?1gJzaIN(VHSZ
z2NUSTW*9|S^OD^-)VE9Fotl*VO#ah&3x@UuD{A0C2qiJh@NFT{YXzpXy^2>eukgga
z0n}VbZe2~%I(HFh5*M6Etc~0Ug(h8hf?qwf4#@@aoWit(03>9^Jsv~v;D;m|(o1JT
zR#8$k8V#uiT01d7Yubcz9Y}zycptrrjz5MtAgL9)LQ*SO>m=0dSb%sL9n|f1zKa*+E;&h
zdy8;0J$;;6T?Vy4CysmY*RQWTC}`h@))=Ww=+y1+Eno5D%}tWt*af|@B~pFPp}BOa
z(d{=vz3>A6IrW0srO;yU$4_v6W86(~=D;~RK5*0`VPd)ThFX0C&j*4ws
zb@||L6_(i5clkL@ZmZk7;_6>*Q(AZV4>wLIHk*qlY&;B2CH1p7vN(DYeXNFhHn)e+
z^^@FkP@QmlNbWg_S;>`!Z7vny^pgBrLbQ6p*nE#myw^9SxOj?Byw~N)AG@GB&e`fD
zBW4@Il0uYh0CQ|sc7A?#Y?hf2Vw6r-=|f#E@g84pt}iyr)fF22ii)MfBI2!dQB+JY
zdz_c5(nAX0o1Gn-X?6{MMNCY(7>Rb2hctyUD25{;iFe_jAaM8Z@~$Sq+HeDMw}e%9
zQo=?D4-&GucpS0XrqwMs-v7j+bN~4Qfgp}yh@G2HW#=Qmeq*i7&VzykyGd+QA!^1;
zRM6Hz+IvU*54*ZHOdJ*2EaM`Se>(pDVCtSZB@%xhq_RRT^l*H0{Q+++
zH7rRT-nb1yk~|`?!u@r_jXd7+Iu48^I8-%zbEJ>U5pGa$|7J
z^Ra~IRy@?YaYngp7odSplHXA{agxRR6cHUu$XR-RCVLg#$PpTk{LZRofK?AbD|N*Z
zH98_mAqB*$gMhYjQyJyf>p1Von_um{=&Lu6oHu67c}L#(`l7vGzj5Te4jpS)bKT=_
zY})k3^Q(*YeuZntpv*VE-YZ|Jl!7aH
zDV3;yMpwoo)EboSrRX>dTA>O2xeS>#mm}KpIOSo$(2z|PMF5?$V}wLHMM90dKtm<^
zwN}DXFlpd%E)h<-h%6jvJH_+q5`Gx-Q{cDG`IRekFWLqA*%8c0py;LbCH0R#h(;
zGfKrq?um10rkMM*RH4h3x{~+APPr<^wXINPiNEU#O+U-()1SLdeadyh%V$kTy}oM^
zs)${-ovZf^+(euva;BNQ|H)OWp4>lK1%(!ix4Ya6qDPDM1QdVEo6ba|0e2s(@W=I?5S
zed=}bKM!1~eXMIAU6-XfR}8weX~L&QFI`tzIcNL0!tOe+HLt`O|Fff{V)Ti?+3Iyd
zaNtU4Q1nS|Zw8@B7E>Nsts+k<{p3t1e)0;E-XNAvb{&OEg%W`vTPC^fk^s-hJ}`pi
zxpRqFO>lIl2a7A+!av-V#liG$A?FllQ@qdQO<9oQHN`#3N}s}g0-Lh`(WUEtbzt(e
z15YeJy`qkCuhf2GnQI;4?99yUu;W_VH?VccKgBVWIqQimGyfuaIKb7ODsAbb`=?Ak
z@T+yCy-%aHr5fZIgrwRS$}s#sxu#Ks8h2*vBxS_clf|2~eu{Wg1d}Z41`}}4SC^k(
zN1u^0j^y1i8J8p-xzx;%B^=4Q52P~c;DZ5c=$LK*Z#9W>8Becmz#YTFF)$ecwji!$
zz8+!foFO+pdLeO;{?;$YD-Yxd~qeN&)>9$!|wiZ3VJX=OWU60c9-;BxQ$dV;%{$N`4F}4hkFw
z!TY`LO<8X!H8iruC=4Qb$R$0aO(E|Sxv~a6Q`S_K^E>jjylSb^PVhAiYDMbE*Ni)QHds=b4|XiFtG9^FT3M5&$=
z+u0-b$Cr#a0gpo$CN4-Ix}?+jWn?Fdly47DQwSNrw^1gk9A|41{8GS;N1FXra*V@+m^xksT@dO+
zGR-LDrt~A5odTxV!9#MAhT+hPLTys$EdcH_AUZ?JhZx6JX;eIibd#DELD?k7X{KPs
z?KDP6ck0gMHfY9x4?;jO{tc)99zmVqve}#&YTy(-e^BbbO%U3L!uZ{GP=8Z<_8>=bCH25JAQS&1h
z8ec}xf!5P3Dekg7Yu&Pg)8|~iq}puD8y6^T$jwO8rMb;%L6>us-TGy)8W}C;dhVm|KmX7KWY>DjYUnWMT8p{n^E%sckdaZrujm
zyU4K_1=-myYt*WQbtd_3tKsl~1x7UtWWWQM!0+6&ksR5{dg1rsG1W*S_}sCure>i-
z{M_QL8XI=x>tdNuj8KcQOkLP1J|sPsE0jE5Pg3*f2E|)oeJWk7yS!A>+n8iC|H_{10AJ~T4h%aK&LXJns
z3wfswXT%s?BQ8UsC<8^}S}M{U|3v&Tzgr|KxsKqU9t6vf*%g(p!X9EGG6dumAqoqL
z_K;1(eL{bQhm~vrCIsadLt9EMu6W`!IFN9T%JKAIMQtj%=5(n7dYc9y3NGcKksG$a
z=O;POnX*)!fu8V`v8v82lPN2HTUx5Mp|vf0_R~w3K0Q0Tt+m0LnkGg|3&p?2atljK
z3uC$BUkk<3_;rB^`Qe^G{JQd;dk=K9AKbfB_3|b0Rnn`NJSjq-$r6f3QamPXJQ?4F
zz_O#PB%E1VS67-DE-7>9Er$1O!aiZ2-5%c&-(h<}D0$j!GMS%_zgj%0F%W2kgHM~p
zCFQ_Bb1>Fn1L^_73ET~tln`MuinQodkX>N^TC?Bm5h_O}XPg@ELj}nJezIVcbyY**
zq)1tM{G`qu7-a*8c!I{@nEC>}TN5I6u6a7WtaVaBVMqGYC*sefcN9KJ&|LxTv=q6S
zlDucgc_wnUBF+$_?y`;o)gEWIK^1a2TV{b-viKk36@W=A>Bio#;>LslqS3+`Y6k^(MtiJ{DXf%h;!9!v}7)5otDR_Nh=
zjZlG6O;`L`yY?dq4JGmKhzX4>uIw5&mK{n~cJL;f@j9u@AOM291Fk
zE_KLgtd$%rQho+pZ&PGEJ0~5@`2DmUV?1R>2nE
zy!nmCuV2*=>RJ}@wFfAN#gw_`$gZ|zGhE%L;t$R{-3RA=`Sv5t$bYan^p4`3(T8rj
zch=@Np15I6W8<0|o_KT9tb1=dG&-jk2a%GK+Wg4dU!Irb6p(xk(6D$%DN>t^(2P7b
zh>9iFtbx}g;X$dS42C2-MuM!!eA00sLl#RsO10^dWJO<`LmEPv+P%aOLy>XGp*s*I
zr&o#ua<`HVB6Vr1FF9VmpFk0!5wa6kGCN2a#>suF$d`oAnfev?_He^Y!koz_8G&ye
zf8sC4@eg=NNIa(|5uZ$tcKALl|8bffRQPlkJJqk
zh7@z6uv4wk?4f)h?!M!SMCVtPXu|$Vzd@tRNK*xJ8n%p{dc&At$C&QoXhBccm|Xw3
zP~kbtmY3!PRB3|;qq84-=(dZOxKzucs%5Sv7vJ{KW3vGwdcwk;9-pXANjFBy-MRJ*
z4JD#!47PyFRbsL_Gc;NsiMy`8U_&{21pYX;RMJ>14zm9D^#G^~Q_WkBuVKR7mV41PK
zt1YYd{+(^@dw#J!{sQs0RJ3$)eebmk?n}1G7GP9{(p_@_1Lp|YgU$3AA8oU;r)Mrf2*R9=sxP@1_
z#>UC`6PwJ4sLNth8bpfc(Mf%z1&C`JJQ+)AeB9|`%ctutK#IxcLV%kIBlivKQ9&{!
zhV2pRm58(^5u4_@tt9q`;!X5Ea!{#H!{U*l+Li)N;vU)~vegC=DJjWHmE208>LfJpW#N_D|Nm=+p(xk{2?6;=fytDTlinx
zX1;Sk?zti((8W)1CrelMMBD62}#dGGJ;F9Xx
zyN@E*rB+bv1T>5)YF3#gNG$13S7`8fniav~_;$q~AaqfC$DgE^p&C?icNjH0S?;Pn
z7mARWK*q^S2R}iQ;NUy_@D)@H9i~eMxf_@N|vCbFup`F2Y_uQYZEpB
z1Ot2|GO8gL1~Q%pk9Z1-8a%2gSjox`SqreLn&K(62D7s~gGaEMo
zIOJ9iX9sb3@CX%T4dEi#Ut$#VBuMh91(IMn)wSd*;i(PC*A^(@KuS=>cd{#8GMAA_
zDygcW3+aK$fnI_o8N?E|4y6*g?DmR4M%dpxd1AyL&InZ6Z7?9HnkcAe@fX-qvh*2M
z;ZU_fpOIoO^jqS?yyi6v#~^E9Bzq3!7_E7;cgpr6YtQ$gp0iMtnyR%ku)`WI{JDMEW2eiws+`twa|AI
zQAmE>np&-nyBy@xC~PCw3aZzST1~`Ip&5yf^I+v5!4r0Fs1St_bk8Ak7yg6>_&aQL
zNQhFbb@}55r@6eBY?-}~aQY`T!{7&`wp#1vDitMJhq~3
z`)K=^x}U62VzHDK=5%+iA;0qA_-(Hqo;RwyH+uCXTAO?L)n8H%@<#k59+uv?v8Tim
zXm*QYuqJ=a{=0LB--O=|l`2NXs0KtM{S$&vsXK5`?`8ajl}NCfr6><0$D6^<9I<1D
z1t9huSmLDL*l_KG?3&67uVgXgmO}5I5?d2PdEnil;F_YcA*gdhB7a&*M+nQpP|}ZZ
zh5M-agey5BpUCP$^imt$@yGbFn|ptK-+?8ywM!1%`oR
z<>V|kIXo*xd6f(}dpX=@ubcO=%7`~)(7zFv7!h_IU}$;sYk~yw;@o+2
zl9|6ZHZd~(x(OWfs*L_nidmp(GpKeU;h{_Y@Ho&r@jP&d9d2Yunufe;^ze#=A42ew
z=$Ad4P)*Ik%xiwTdHsu%EJ2GoXqouCb(>$hZq~GkgMWAC1)PI_nKWG&ZQpWu?u;Kc
z;;^MK+g)VAsm(Xcp7XYXr^uY-Sx9)PO^k7mXLYkj5#;Fw0Z6CCl0>t
zbgGIbzp`S^OjAsjXx4k7m!jwQ2B6RZ7#%)XN#=A8KzwbfFyhtD9z@
z07#I$ys(@aluSf!dW)$-ki3Vaj%>(osDUd9qby)%$R-P_gWgS%;@U+6xAZ=7*_7&q
z7fsgZg+qqaqOJRHoV@0@Ki=w|dT?c9+lK2;I8_tlk5{Z6J#qi?#(ZJ6dQsWzQ0%(F
zD~p$l|2$Sw;as%mhtulTESa4b8siszVnJ4B1yU^Y#&)y`(J7Zb(L43<1&bZ36rH9W
z>8+jTKh&!kv*D_#Gq2mwCOCzqzs~WKcyHeETThO#A$};^BQ~6E)=#=n%s}m_hW!|H4Pm2ulnGb5`sF;bxEdI5h|E(cy{4O~NO!8=Ovtxp_pU6Eu5h
zZk$wZfAT;H_esm?kc3wNJ7a$~l{yh+GMi0s^Hn>`jAGPiwZb;23aPts)NDr3%UMcC
zt;Sf?Smp$LvWECQq7W-cc|p&Vn`;Q#@|%*)3-h7WMa2fiP^j8ff@@<@6BQqe1~q#K
zi=o_iaL^hkaaGen3;c|*uK6%s%^saVZvkFLpOzuC{0fp~jf8Lk4-lw^bv>e$YkotBRJ%lCvF3fO>Go66|eOF=;
z>yPzgvr@(QE@$jsXCSZKDdK>$TqHesf8Nv+BOznMA>HK+RbAs|*dBX}JQF>%5#YKf=WF$&a
zOHWPPxi}W<&&W3OyGy0thtg3Wa&7QRS89Z-k&t+w{H9=KTq3`{a38inR4+sCQ7OrC
zpa?|x{Hz|c6isD|P%FcHcYwk?We0eeXGmLzAC_Eu6eUVdi&a3MRl|J`4YGS>C_7fl
zi3RMEf*3+%;=lzJG-Htyq|1%w>w6%+N$c;yVG
z6HE0*P91=Mr8*?{FG5X-mXiD6wDk#Bf|Xo1$@LnIMhTb#`T!x&JYYW9ZIoA(lz9-w
zm}Uq#a%BM!Aqm5%U=$xRWf198G~J1)7Uh#rK`I1{s$j4t
zijS1CiKv&z-jx+vybh0qN1^x^kXSkN*e=Y`bU)3M#FG~McoYg_(}>VYMZHm{)#@r?
zK=S~CR!VOOg}FJ%brtj(cY^Szu4x(}$tjv9$mX|#Y$(Bucf`Bi-GB4C#p7Y%e;>7C7^?t3DnG|5SWTP=V-PkVs2t>N+6;oPhU}`ta#?WL)9y|Nh^hQ&<;|A&>iSbbRn{#
z=@RnlBytF8qgCA^Ia8@W2`rATGScNT9L=twx!JzY8XKw)s81OPNIeMd7J~}&5MX}^
zO-sp#Lj;+nFb*-R
zS|@<(Y7w0g`^aCLYf)>q3hJii2k-vn(#1c&^YWU?HjN-`O#?7=#v`io8JjvfHq9tk
zH>vH}UZ=5S`i}0a?w)+({%s`%H8|1e^k&=DDwaQ{(j$TwJe6aG^T9Ii3`e?^5@vPmGyMH#{;4#Fj;_uttgb&*{b7Jx%t_&s`l}bQl0RpnK$p>Flth;
zb46S8Row=cAs*J1M#i^SrNy5{P6u4hRq%BV*}*w9k0H-707ScVkZ-esTi=lz4fwe~FDOUQCm%@<*c!RR2DE?p_
zHkXA!5nd^YjSuCNx^OU5jUZHs$%ME8b>%oRx+EbTk7BYo#7z)ez_+xnjSeK-?dnUo
zjHnKVEGAQli`=>&AeV$r7PyqB<;Z;adDMPV9y|;|uEWq~!}8&UL{31ijM4FG39QQP
z5SuP4o2EQ1K3NV#Pn#hRw@rMJIsURx$^Cutm*X#UFP%_{6(|%lEXGROqjYwugC}Rv
zpC)sjyg0&Z$lf_)aq=xC9tMJdZwQ>VjJue|u^xnnk4A3LR{VrAjzbrX
z@Nr1Vo<(UL12ax{fn1n0=qTC6$=A^^ECT7%r|ToT4+)&Sbs%H#L?!BoT;bfYkX-p{
zCe_l2<8OS8^7;@%?ZZ1aK$A)`91w+zcxY1sOgym)9do#4hOipt+rq%t_Jv#<-g^A1
z;^M0we`^C_lLvm#y>)6)d<}0tDO(EP)P(UhMN_wS|KI^vDB=pW?YMWvihFmo5m=a6
zxc&0mW~xKDh|c5rP~@o#nT4wd-kEvZ<=YEqhLT3Uhmp%(3jMzfQF0~ob%af$8)nl~
z(0EWmhjgDx4L%7M2V{0_5O1oCCzV`Wc=QtA&8E(nuGMzy+ES+e6rX
zr2X^LjFjRo|Jl(f(z(!K2|nbtd4oA(UuI^09l-<|_&_iLyJI|JLpww!Mh6%!iE2*4
z3p^)w7=n-ziG~b>?!v8#X^@esvJ{6@RMG(BStMB|@kL*G+DDqY{DFQcOtYYxAVii)
z`0X39d*ofJ=O2IL@%RmZ66{ngvGjDj->#Nq&yNHm65VcsCMOinW6Z%G&WYTLM2ZUH>CI%GWYOL
z0vNJaPBMYCrndvZ78hDrKnF2cv{8U^U@V*)YQft<{C2jf_!v5?72RHhw|gd
zmJNO24)RB%8Kd#XEvS6V>lQ)l&Bh#V=VBh+TQEEABQ(S7$Qe9BXv9Q=5>oafj?Q}%
zzcqK^%cj(s)>Xs0t>kM+E<+e$K#$B?m)sAy@vw|M?hzw=D)rz2CEhH}Au@U_0qCI=
zDHV%F6euYq4A9f9@rLE5a>6Syz?4g+tP%20gj^9iNx_)39E{LzF*20S*GJ5yuogw<
zMJ^OniA1OP+qpyL#2_C95>+WiuRO#;xp!iDqU&_Ls9q!k*uk!3t`rkK1^H2(#0ydW
zsCeA?T%||xWo{|ZFSt&gd!&@+r~Y^ITF5!9Ckxsy_gvXKY$jAF`GyMx6^4j^tE37@
z$@@I+ue6>tI)evW&o_HDFP^LOTad7ZdVT#tozG&;)4sYb#b-pNVb`CIr1?3N8Y)N{
zm%!!1$k}1w<}`}W#UC|u+f{hWWOrF&p5s}hjzaO<%{-D8h3y%IuC&m6_9?>{*$u$zQjMAE>QHNWc76F@-PPG8rYt4f!RyncXb|hYjJR9!B2mYenOU4iY;sws(~VQ&
zSEuSz{w6iIIV-)ev=Fm9n6nnR-I)QSA@GVh!{#yogQjJw>NI&atc5KOT?-mRJq`32#0xA|YTGEe-eR8uNa=RMX?wLfM`fAz;XW%Lprf8F?e
z3{!q3wYUm1ruwVeL&B9vtY2r)`dafy!%+K|%?_${coFn$;f9e?BhH9LbMO)>^*V5W
zd>y@(;4}JCw04IH^C$RHN--adyKzfn8D0dhVauQwF$pePjye9erNAAtx7aXqqo_*dgdhWzvj~
z36VDB03GO4anV{dXD?N0jBn^|dV7(L?~sO9^tnP>)MX!eV+Qn^M)C^KY-wFPZk|1`
zo#r4DRw>>bC86ciOc|ttfyJQiHBm@XVl`>_@+s(GZ{^%E`GUZcZ=&*saFTCIqn}U)
zd2YGfA7tbRQC0KF&tltW-@Ky>6S}E#G!jOW2F=m{)MR}EPKmoYctJ7rV$e4bVdVWm
zn?ior5Zf6G6wPGF1u%9DkmsYpK(jNOrz+kWv!
zdAc9%mYAND;rzP}ZJJypC37rz=%#(WT^P5EmQkfNG&N%upLOp=9VjEpeQ_~3)7Jd)
z7q_)Ux{ZRxU+9RjEYBz>?z84s^X42_T*=KRHC-=$mDSa|@1}l7<1OYjc^I)U+#;bF%q%^SxOzoFcJ=P;5qg}uOPD#Ry+45$}K+lo`VDvTPIgtm?jv1O});P7Ea-+rMX^hE30ZSq~!D&t?KmZvUxwM(WYs#3fCYrUrP^1@1R94|C?rqzIglo
zYsQtA1tt_U?v70U$?aEEJW6UpIz>8N^B6rp-eZ3C^0TIRJ?2}z%O|#No>hsLXg6ou
zj48LOHG;-Ex?|kuii40m)Tuy7Um|n03;scPs3D=qKu2Ujl4Il~#XN$Tv`FFxHIEhr
zp_P-hZKY;tOXejWN*LM;bqS%Viw4^ltl!-}u2sojo3!tzOQu}BxSG<+%x&kdTi71r
z*kUjvt7Fm5F-m?HCAO(9p{%c-%X%^Q;nZ!};hq9Y`HDqbRvwrz`LdOKk`YS&QnR%7
z-Rl>$2eXVc{Fs+~&LjJ$iMGWT{%9H{%>~=$uiM>@M@S#L>zq!LN=_M@Ol5E4iDYy?
zQ@~Vy-8^Fk?i!ydrI)QdFiA--L-Z$sE@?(C%CnfkNBmNkNhk&>swB`<#P|!uag{lLPGdNoE~DJc0k;ys9AOFZ
zM^ZrkkU_-XMS92oU@}G3(BsM(M0na9_(Er3Y$?r6sLZed(TYJla9+s>Q!Tj!sP)Vi
zEopSZ3#8Dgg(yx#HYKHO+k$c*qP{~4Ns8JjUK@|7i7fuv;XU&!D(3Gw{IkWeX!4dA
z9kQcid>x6D+xwsysfr~XDX-Do5;Uw=8ly}~Rho7td5?}sH%Y#Qv_5c}BvCOk;udt<
zJ7p*;4I~bf#+QxQ!8H@l#iB6<)F)bbJ^n|%0ktV}zchM?8vVP(sB}L1Mu+#6fbn-+
z%W8OSNVb)h8%)W=*r|5_<^WA_bTP;)i%+V93X|gQoM}bKLMd8TN!iaFD4^Y11hOMw
zLqNr$6(y5N5TkfJ{ph)TH|{4`d!Di8hAv!df-vAvW36_L{sJQ`GCQmDxhwp@~;qdhwXlEWJJ}
zb+#^Tg=f1r4_k!d0+Xct(x2hvz
zBs*KD)o64^y{#rPp-`jMY6>SrYHWI=PNUK4Fga4+Yw-u--#pi;7R9m8WAgr~uZpRG
zYd3DZHW2&f$@p7Gk3=FzjtWS>M^s4W-Fo_MDzX;{@sQS%v>1UZnFFKKdYiX%Y@{N`oMWo+
zJ8K6`!hLOL^^7g>GufY);$)46tXFSlV65L*
z5OiAg#wL%WuA$N0a>I}Bx%p6Su-KWdRcp--GyXMdt=>@-t~+$oJ$Kv?soz%VYcyt<
zMZuKcTAJJLvlM4({MM|ZvNFr)LpR=h?cNHrEnTfrYgP7Oy2-BBVI3f~@}g^R`Qf3_
zma?*