[General]Add an option for telemetry opt-in and visualization(#34078)

* Data diagnostics opt-in

* [c++] Drop DROP_PII flag

* Bump telemtry package to 2.0.2

* Drop DropPii from custom actions

* Cleanup

* Do not start manually C# EtwTrace. FZ engine exit event.

* ImageResizer, PowerRename, FileLocksmith prev handlers

* Revert C# handlers exe logging

* Revert "Revert C# handlers exe logging"

This reverts commit 4c75a3953b.

* Do not recreate EtwTrace

* consume package

* xaml formatting

* Fix deps.json audit

* Update telem package paths

* Address PR comments

* Fix AdvancedPaste close on PT close

* Override etl file name for explorer loaded dlls
Start/stop tracer when needed for explorer loaded dlls to prevent explorer overload

* Fix setting desc

* Fix missing events

* Add infobar to restart when enable data viewing

* Flush on timer every 30s

* [Settings] Update View Data diagnostic description text
[New+] Add tracer

* Show Restart info bar for both enable/disable data viewer

* Fix newplus

* Fix stuck on restart and terminate AdvPaste exe on destroy()

* [Installer] Add tracer

* Address PR comment

* Add missing tracers

* Exclude etw dir from BugReport

* Fix bad merge

* [Hosts] Proper exit on initial dialog

* [OOBE] Make Data diagnostic setting visible without scroll

* [OOBE] Add hiperlynk to open general settings

* Disable data view on disabling data diagnostics

* Don't disable View data button

* Fix disabling data viewing

* Add missing dot

* Revert formatting
This commit is contained in:
Stefan Markovic
2024-10-24 22:04:32 +02:00
committed by GitHub
parent f9127b63a5
commit 133aa85f2b
269 changed files with 2622 additions and 1256 deletions

View File

@@ -0,0 +1,102 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ManagedCommon;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
public class ETLConverter
{
private const int TracerptConversionTimeout = 60000; // 60 seconds in milliseconds
private const string ETLConversionOutputFormat = "xml"; // Assuming XML output format
private readonly string etwDirPath;
private readonly string tracerptPath;
public ETLConverter(string etwDirPath, string tracerptPath)
{
this.etwDirPath = etwDirPath;
this.tracerptPath = tracerptPath;
}
private bool ETLConversionsFailed { get; set; }
public async Task ConvertDiagnosticsETLsAsync(CancellationToken cancellationToken = default)
{
var etlConversionTasks = new List<Task>();
var directoryInfo = new DirectoryInfo(etwDirPath);
foreach (var fileInfo in directoryInfo.GetFiles("*.etl", SearchOption.AllDirectories))
{
var task = Task.Run(() => ConvertETLAsync(fileInfo.FullName, cancellationToken), cancellationToken);
etlConversionTasks.Add(task);
}
try
{
await Task.WhenAll(etlConversionTasks);
}
catch (Exception)
{
ETLConversionsFailed = true;
}
if (ETLConversionsFailed)
{
throw new InvalidOperationException("One or more ETL conversions failed.");
}
}
private void ConvertETLAsync(string etlFilePathToConvert, CancellationToken cancellationToken)
{
var outputFilePath = Path.ChangeExtension(etlFilePathToConvert, $".{ETLConversionOutputFormat}");
if (File.Exists(outputFilePath))
{
File.Delete(outputFilePath);
}
var tracerPtArguments = $"\"{etlFilePathToConvert}\" -o \"{outputFilePath}\" -lr -y -of {ETLConversionOutputFormat}";
var startInfo = new ProcessStartInfo
{
FileName = tracerptPath + "\\tracerpt.exe",
Arguments = tracerPtArguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
};
using (var process = Process.Start(startInfo))
{
if (process == null)
{
Logger.LogError("Failed to start tracerpt process.");
}
var processExited = process.WaitForExit(TracerptConversionTimeout);
if (!processExited)
{
process.Kill();
Logger.LogError("ETL conversion process timed out.");
}
var exitCode = process.ExitCode;
if (exitCode != 0)
{
Logger.LogError($"ETL conversion failed with exit code {exitCode}.");
}
}
}
}
}

View File

@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Threading;
using Microsoft.UI.Dispatching;
namespace Microsoft.PowerToys.Settings.UI.Helpers
{
public static class NativeEventWaiter
{
public static void WaitForEventLoop(string eventName, Action callback)
{
var dispatcherQueue = DispatcherQueue.GetForCurrentThread();
new Thread(() =>
{
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
while (true)
{
if (eventHandle.WaitOne())
{
dispatcherQueue.TryEnqueue(() => callback());
}
}
}).Start();
}
}
}

View File

@@ -11,6 +11,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
public static class StartProcessHelper
{
public const string ColorsSettings = "ms-settings:colors";
public const string DiagnosticsAndFeedback = "ms-settings:privacy-feedback";
public static string AnimationsSettings => OSVersionHelper.IsWindows11()
? "ms-settings:easeofaccess-visualeffects"

View File

@@ -70,6 +70,8 @@ namespace Microsoft.PowerToys.Settings.UI
public static Action<string> IPCMessageReceivedCallback { get; set; }
public ETWTrace EtwTrace { get; private set; } = new ETWTrace();
/// <summary>
/// Initializes a new instance of the <see cref="App"/> class.
/// Initializes the singleton application object. This is the first line of authored code
@@ -88,6 +90,13 @@ namespace Microsoft.PowerToys.Settings.UI
InitializeComponent();
UnhandledException += App_UnhandledException;
NativeEventWaiter.WaitForEventLoop(
Constants.PowerToysRunnerTerminateSettingsEvent(), () =>
{
EtwTrace?.Dispose();
Environment.Exit(0);
});
}
private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e)

View File

@@ -5,6 +5,8 @@
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
mc:Ignorable="d">
<controls:OOBEPageControl x:Uid="Oobe_Overview" HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/PTHero.png">
@@ -17,6 +19,35 @@
<TextBlock x:Uid="Oobe_Overview_DescriptionLinkText" TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
<StackPanel
Orientation="Vertical"
Spacing="8"
Visibility="{x:Bind ShowDataDiagnosticsSetting, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<TextBlock
x:Uid="Oobe_Overview_Telemetry_Title"
Margin="0,20,0,0"
Style="{StaticResource SubtitleTextBlockStyle}" />
<TextBlock x:Uid="Oobe_Overview_Telemetry_Desc" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<tkcontrols:SettingsCard
x:Uid="Oobe_Overview_EnableDataDiagnostics"
HeaderIcon="{ui:FontIcon Glyph=&#xE9D9;}"
IsEnabled="{x:Bind ShowDataDiagnosticsSetting, Mode=OneWay}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind EnableDataDiagnostics, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<HyperlinkButton
x:Uid="Oobe_Overview_DiagnosticsAndFeedback_Settings_Link"
Margin="-8,0,0,0"
Click="GeneralSettingsLaunchButton_Click" />
<HyperlinkButton
x:Uid="Oobe_Overview_DiagnosticsAndFeedback_Link"
Margin="-8,0,0,0"
NavigateUri="https://aka.ms/powertoys-data-and-privacy-documentation" />
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>

View File

@@ -2,9 +2,11 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
@@ -14,9 +16,46 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public OobePowerToysModule ViewModel { get; set; }
private bool _enableDataDiagnostics;
public bool EnableDataDiagnostics
{
get
{
return _enableDataDiagnostics;
}
set
{
if (_enableDataDiagnostics != value)
{
_enableDataDiagnostics = value;
DataDiagnosticsSettings.SetEnabledValue(_enableDataDiagnostics);
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
ShellPage.ShellHandler?.SignalGeneralDataUpdate();
});
}
}
}
public bool ShowDataDiagnosticsSetting => GetIsDataDiagnosticsInfoBarEnabled();
private bool GetIsDataDiagnosticsInfoBarEnabled()
{
var isDataDiagnosticsGpoDisallowed = GPOWrapper.GetAllowDataDiagnosticsValue() == GpoRuleConfigured.Disabled;
return !isDataDiagnosticsGpoDisallowed;
}
public OobeOverview()
{
this.InitializeComponent();
_enableDataDiagnostics = DataDiagnosticsSettings.GetEnabledValue();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Overview]);
DataContext = ViewModel;
}
@@ -31,6 +70,16 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
ViewModel.LogOpeningSettingsEvent();
}
private void GeneralSettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(GeneralPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();

View File

@@ -6,18 +6,66 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
xmlns:ui="using:CommunityToolkit.WinUI"
Loaded="Page_Loaded"
mc:Ignorable="d">
<Grid Margin="0,24,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<tkcontrols:SettingsCard
x:Name="WhatsNewDataDiagnosticsInfoBar"
x:Uid="Oobe_WhatsNew_DataDiagnostics_InfoBar"
Margin="0,-24,0,0"
Background="{ThemeResource InfoBarInformationalSeverityBackgroundBrush}"
IsTabStop="{x:Bind ShowDataDiagnosticsInfoBar, Mode=OneWay}"
Visibility="{x:Bind ShowDataDiagnosticsInfoBar, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
<tkcontrols:SettingsCard.HeaderIcon>
<FontIcon Foreground="{ThemeResource InfoBarInformationalSeverityIconBackground}" Glyph="&#xF167;" />
</tkcontrols:SettingsCard.HeaderIcon>
<tkcontrols:SettingsCard.Description>
<StackPanel>
<TextBlock x:Name="WhatsNewDataDiagnosticsInfoBarDescText">
<Hyperlink NavigateUri="https://aka.ms/powertoys-data-and-privacy-documentation">
<Run x:Uid="Oobe_WhatsNew_DataDiagnostics_InfoBar_Desc" />
</Hyperlink>
</TextBlock>
<TextBlock x:Name="WhatsNewDataDiagnosticsInfoBarDescTextYesClicked" Visibility="Collapsed">
<Run x:Uid="Oobe_WhatsNew_DataDiagnostics_Yes_Click_InfoBar_Desc" />
<Hyperlink Click="DataDiagnostics_OpenSettings_Click">
<Run x:Uid="Oobe_WhatsNew_DataDiagnostics_Yes_Click_OpenSettings_Text" />
</Hyperlink>
</TextBlock>
</StackPanel>
</tkcontrols:SettingsCard.Description>
<StackPanel Orientation="Horizontal" Spacing="8">
<Button
x:Name="DataDiagnosticsButtonYes"
x:Uid="Oobe_WhatsNew_DataDiagnostics_Button_Yes"
Click="DataDiagnostics_InfoBar_YesNo_Click"
CommandParameter="Yes" />
<HyperlinkButton
x:Name="DataDiagnosticsButtonNo"
x:Uid="Oobe_WhatsNew_DataDiagnostics_Button_No"
Click="DataDiagnostics_InfoBar_YesNo_Click"
CommandParameter="No" />
<Button
Margin="16,0,0,0"
Click="DataDiagnostics_InfoBar_Close_Click"
Content="{ui:FontIcon Glyph=&#xE894;,
FontSize=16}"
Style="{StaticResource SubtleButtonStyle}" />
</StackPanel>
</tkcontrols:SettingsCard>
<StackPanel
Grid.Row="0"
Grid.Row="1"
Margin="32,0,0,16"
VerticalAlignment="Top"
Orientation="Vertical">
@@ -33,7 +81,7 @@
<InfoBar
x:Name="ErrorInfoBar"
x:Uid="Oobe_WhatsNew_LoadingError"
Grid.Row="1"
Grid.Row="2"
VerticalAlignment="Top"
IsClosable="False"
IsOpen="False"
@@ -42,14 +90,14 @@
<InfoBar
x:Name="ProxyWarningInfoBar"
x:Uid="Oobe_WhatsNew_ProxyAuthenticationWarning"
Grid.Row="1"
Grid.Row="2"
VerticalAlignment="Top"
IsClosable="False"
IsOpen="False"
IsTabStop="True"
Severity="Warning" />
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
<Grid Margin="32,24,32,24">
<ProgressRing
x:Name="LoadingProgressRing"

View File

@@ -15,9 +15,13 @@ using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CommunityToolkit.WinUI.UI.Controls;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
@@ -43,6 +47,8 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
public OobePowerToysModule ViewModel { get; set; }
public bool ShowDataDiagnosticsInfoBar => GetShowDataDiagnosticsInfoBar();
/// <summary>
/// Initializes a new instance of the <see cref="OobeWhatsNew"/> class.
/// </summary>
@@ -53,6 +59,33 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
DataContext = ViewModel;
}
private bool GetShowDataDiagnosticsInfoBar()
{
var isDataDiagnosticsGpoDisallowed = GPOWrapper.GetAllowDataDiagnosticsValue() == GpoRuleConfigured.Disabled;
if (isDataDiagnosticsGpoDisallowed)
{
return false;
}
bool userActed = DataDiagnosticsSettings.GetUserActionValue();
if (userActed)
{
return false;
}
bool registryValue = DataDiagnosticsSettings.GetEnabledValue();
bool isFirstRunAfterUpdate = (App.Current as Microsoft.PowerToys.Settings.UI.App).ShowScoobe;
if (isFirstRunAfterUpdate && registryValue == false)
{
return true;
}
return false;
}
/// <summary>
/// Regex to remove installer hash sections from the release notes.
/// </summary>
@@ -166,5 +199,65 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
});
}
}
private void DataDiagnostics_InfoBar_YesNo_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
string commandArg = string.Empty;
if (sender is Button senderBtn)
{
commandArg = senderBtn.CommandParameter.ToString();
}
else if (sender is HyperlinkButton senderLink)
{
commandArg = senderLink.CommandParameter.ToString();
}
if (string.IsNullOrEmpty(commandArg))
{
return;
}
// Update UI
if (commandArg == "Yes")
{
WhatsNewDataDiagnosticsInfoBar.Header = ResourceLoaderInstance.ResourceLoader.GetString("Oobe_WhatsNew_DataDiagnostics_Yes_Click_InfoBar_Title");
}
else
{
WhatsNewDataDiagnosticsInfoBar.Header = ResourceLoaderInstance.ResourceLoader.GetString("Oobe_WhatsNew_DataDiagnostics_No_Click_InfoBar_Title");
}
WhatsNewDataDiagnosticsInfoBarDescText.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
WhatsNewDataDiagnosticsInfoBarDescTextYesClicked.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
DataDiagnosticsButtonYes.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
DataDiagnosticsButtonNo.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
// Set Data Diagnostics registry values
if (commandArg == "Yes")
{
DataDiagnosticsSettings.SetEnabledValue(true);
}
else
{
DataDiagnosticsSettings.SetEnabledValue(false);
}
DataDiagnosticsSettings.SetUserActionValue(true);
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
ShellPage.ShellHandler?.SignalGeneralDataUpdate();
});
}
private void DataDiagnostics_InfoBar_Close_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
WhatsNewDataDiagnosticsInfoBar.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
}
private void DataDiagnostics_OpenSettings_Click(Microsoft.UI.Xaml.Documents.Hyperlink sender, Microsoft.UI.Xaml.Documents.HyperlinkClickEventArgs args)
{
Common.UI.SettingsDeepLink.OpenSettings(Common.UI.SettingsDeepLink.SettingsWindow.Overview, true);
}
}
}

View File

@@ -381,6 +381,56 @@
IsTabStop="{x:Bind ViewModel.IsExperimentationGpoDisallowed, Mode=OneWay}"
Severity="Informational" />
</controls:SettingsGroup>
<controls:SettingsGroup x:Uid="General_DiagnosticsAndFeedback" Visibility="Visible">
<StackPanel>
<HyperlinkButton
x:Uid="GeneralPage_DiagnosticsAndFeedback_Link"
Margin="-8,0,0,0"
NavigateUri="https://aka.ms/powertoys-data-and-privacy-documentation" />
<tkcontrols:SettingsCard
x:Uid="GeneralPage_EnableDataDiagnostics"
HeaderIcon="{ui:FontIcon Glyph=&#xE9D9;}"
IsEnabled="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.EnableDataDiagnostics, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsExpander
x:Uid="GeneralPage_ViewDiagnosticData"
HeaderIcon="{ui:FontIcon Glyph=&#xE7EF;}"
IsEnabled="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
IsExpanded="True">
<tkcontrols:SettingsExpander.Items>
<tkcontrols:SettingsCard x:Uid="GeneralPage_EnableViewDiagnosticData">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsEnabled="{x:Bind ViewModel.EnableDataDiagnostics, Mode=TwoWay}"
IsOn="{x:Bind ViewModel.EnableViewDataDiagnostics, Mode=TwoWay}" />
</tkcontrols:SettingsCard>
<tkcontrols:SettingsCard
x:Uid="GeneralPage_ViewDiagnosticDataViewer"
ActionIcon="{ui:FontIcon Glyph=&#xE8A7;}"
Click="ViewDiagnosticData_Click"
IsClickEnabled="True" />
</tkcontrols:SettingsExpander.Items>
</tkcontrols:SettingsExpander>
<InfoBar
x:Uid="GeneralPage_ViewDiagnosticDataViewerInfo"
IsClosable="False"
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.ViewDiagnosticDataViewerChanged}"
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.ViewDiagnosticDataViewerChanged}"
Severity="Informational">
<InfoBar.ActionButton>
<Button x:Uid="GeneralPage_ViewDiagnosticDataViewerInfoButton" Click="Click_ViewDiagnosticDataViewerRestart" />
</InfoBar.ActionButton>
</InfoBar>
<InfoBar
x:Uid="GPO_SettingIsManaged"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay}"
IsTabStop="{x:Bind ViewModel.IsDataDiagnosticsGPOManaged, Mode=OneWay}"
Severity="Informational" />
</StackPanel>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>

View File

@@ -18,7 +18,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
/// <summary>
/// General Settings Page.
/// </summary>
public sealed partial class GeneralPage : Page
public sealed partial class GeneralPage : Page, IRefreshablePage
{
private static DateTime OkToHideBackupAndRestoreMessageTime { get; set; }
@@ -99,6 +99,18 @@ namespace Microsoft.PowerToys.Settings.UI.Views
}
}
private void OpenDiagnosticsAndFeedbackSettings_Click(object sender, RoutedEventArgs e)
{
try
{
Helpers.StartProcessHelper.Start(Helpers.StartProcessHelper.DiagnosticsAndFeedback);
}
catch (Exception ex)
{
Logger.LogError("Error while trying to open the system Diagnostics & Feedback settings", ex);
}
}
private void RefreshBackupRestoreStatus(int delayMs = 0)
{
Task.Run(() =>
@@ -136,5 +148,20 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{
ViewModel.Restart();
}
private void Click_ViewDiagnosticDataViewerRestart(object sender, RoutedEventArgs e)
{
ViewModel.Restart();
}
public void RefreshEnabledState()
{
ViewModel.RefreshSettingsOnExternalChange();
}
private void ViewDiagnosticData_Click(object sender, RoutedEventArgs e)
{
ViewModel.ViewDiagnosticData();
}
}
}

View File

@@ -2143,6 +2143,51 @@ Take a moment to preview the various utilities listed or view our comprehensive
<data name="Oobe_Overview_DescriptionLinkText.Text" xml:space="preserve">
<value>Documentation on Microsoft Learn</value>
</data>
<data name="Oobe_Overview_Telemetry_Title.Text" xml:space="preserve">
<value>Help us make PowerToys better</value>
</data>
<data name="Oobe_Overview_Telemetry_Desc.Text" xml:space="preserve">
<value>Diagnostics &amp; feedback helps us to improve PowerToys and keep it secure, up to date, and working as expected.</value>
</data>
<data name="Oobe_Overview_DiagnosticsAndFeedback_Settings_Link.Content" xml:space="preserve">
<value>View more diagnostic data settings</value>
</data>
<data name="Oobe_Overview_DiagnosticsAndFeedback_Link.Content" xml:space="preserve">
<value>Learn more about the information PowerToys logs &amp; how it gets used</value>
</data>
<data name="Oobe_Overview_EnableDataDiagnostics.Header" xml:space="preserve">
<value>Diagnostic data</value>
</data>
<data name="Oobe_Overview_EnableDataDiagnostics.Description" xml:space="preserve">
<value>Helps inform bug fixes, performance, and product decisions</value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_InfoBar.Header" xml:space="preserve">
<value>Turn on diagnostic data to help us improve PowerToys?</value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_InfoBar_Desc.Text" xml:space="preserve">
<value>PowerToys diagnostic data is completely optional.</value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_InfoBar_Button_Enable.Content" xml:space="preserve">
<value>Enable</value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_Yes_Click_InfoBar_Title" xml:space="preserve">
<value>Thank you for helping to make PowerToys better!</value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_No_Click_InfoBar_Title" xml:space="preserve">
<value>Preference updated.</value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_Yes_Click_InfoBar_Desc.Text" xml:space="preserve">
<value>You can change this at any time from </value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_Yes_Click_OpenSettings_Text.Text" xml:space="preserve">
<value>settings.</value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_Button_Yes.Content" xml:space="preserve">
<value>Yes</value>
</data>
<data name="Oobe_WhatsNew_DataDiagnostics_Button_No.Content" xml:space="preserve">
<value>No</value>
</data>
<data name="ReleaseNotes.Content" xml:space="preserve">
<value>Release notes</value>
</data>
@@ -3852,6 +3897,33 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="GeneralPage_EnableExperimentation.Header" xml:space="preserve">
<value>Allow experimentation with new features</value>
</data>
<data name="General_DiagnosticsAndFeedback.Header" xml:space="preserve">
<value>Diagnostics &amp; feedback</value>
</data>
<data name="GeneralPage_DiagnosticsAndFeedback_Link.Content" xml:space="preserve">
<value>Learn more about the information we log &amp; how it gets used</value>
</data>
<data name="GeneralPage_EnableDataDiagnostics.Header" xml:space="preserve">
<value>Diagnostic data</value>
</data>
<data name="GeneralPage_EnableDataDiagnostics.Description" xml:space="preserve">
<value>Helps inform bug fixes, performance, and improvements</value>
</data>
<data name="GeneralPage_ViewDiagnosticData.Header" xml:space="preserve">
<value>View diagnostic data</value>
</data>
<data name="GeneralPage_EnableViewDiagnosticData.Header" xml:space="preserve">
<value>Enable viewing</value>
</data>
<data name="GeneralPage_EnableViewDiagnosticData.Description" xml:space="preserve">
<value>Uses up to 1GB (or more) of hard drive space on your PC</value>
</data>
<data name="GeneralPage_ViewDiagnosticDataViewer.Header" xml:space="preserve">
<value>Diagnostic data viewer</value>
</data>
<data name="GeneralPage_ViewDiagnosticDataViewer.Description" xml:space="preserve">
<value>Generate .xml files containing readable diagnostic data. Folder may include .xml and .etl files</value>
</data>
<data name="Shell_AdvancedPaste.Content" xml:space="preserve">
<value>Advanced Paste</value>
<comment>Product name: Navigation view item name for Advanced Paste</comment>
@@ -4385,7 +4457,7 @@ Activate by holding the key for the character you want to add an accent to, then
</data>
<data name="Oobe_NewPlus_TipsAndTricks.Text" xml:space="preserve">
<value>You can have multiple templates of the same file type, and you can even template folders!</value>
</data>
</data>
<data name="Workspaces.ModuleDescription" xml:space="preserve">
<value>Workspaces is a quick and easy way to launch a set of applications to custom positions and configurations with one-click.</value>
</data>
@@ -4485,4 +4557,10 @@ Activate by holding the key for the character you want to add an accent to, then
<data name="Chinese_Traditional_Language" xml:space="preserve">
<value>Chinese (Traditional)</value>
</data>
<data name="GeneralPage_ViewDiagnosticDataViewerInfo.Title" xml:space="preserve">
<value>Restart PowerToys for enable viewing change to take effect.</value>
</data>
<data name="GeneralPage_ViewDiagnosticDataViewerInfoButton.Content" xml:space="preserve">
<value>Restart</value>
</data>
</root>

View File

@@ -137,24 +137,32 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
public void ModuleEnabledChangedOnSettingsPage()
{
ActiveModules.Clear();
DisabledModules.Clear();
generalSettingsConfig = _settingsRepository.SettingsConfig;
foreach (DashboardListItem item in _allModules)
try
{
item.IsEnabled = ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, item.Tag);
if (item.IsEnabled)
{
ActiveModules.Add(item);
}
else
{
DisabledModules.Add(item);
}
}
ActiveModules.Clear();
DisabledModules.Clear();
OnPropertyChanged(nameof(ActiveModules));
OnPropertyChanged(nameof(DisabledModules));
generalSettingsConfig = _settingsRepository.SettingsConfig;
foreach (DashboardListItem item in _allModules)
{
item.IsEnabled = ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, item.Tag);
if (item.IsEnabled)
{
ActiveModules.Add(item);
}
else
{
DisabledModules.Add(item);
}
}
OnPropertyChanged(nameof(ActiveModules));
OnPropertyChanged(nameof(DisabledModules));
}
catch (Exception ex)
{
Logger.LogError($"Updating active/disabled modules list failed: {ex.Message}");
}
}
private ObservableCollection<DashboardModuleItem> GetModuleItems(ModuleType moduleType)

View File

@@ -16,11 +16,13 @@ using System.Threading.Tasks;
using global::PowerToys.GPOWrapper;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
using Microsoft.PowerToys.Telemetry;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
@@ -143,12 +145,29 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
_autoDownloadUpdatesIsGpoDisabled = GPOWrapper.GetDisableAutomaticUpdateDownloadValue() == GpoRuleConfigured.Enabled;
_experimentationIsGpoDisallowed = GPOWrapper.GetAllowExperimentationValue() == GpoRuleConfigured.Disabled;
_showWhatsNewAfterUpdatesIsGpoDisabled = GPOWrapper.GetDisableShowWhatsNewAfterUpdatesValue() == GpoRuleConfigured.Enabled;
_enableDataDiagnosticsIsGpoDisallowed = GPOWrapper.GetAllowDataDiagnosticsValue() == GpoRuleConfigured.Disabled;
if (_enableDataDiagnosticsIsGpoDisallowed)
{
_enableDataDiagnostics = false;
}
else
{
_enableDataDiagnostics = DataDiagnosticsSettings.GetEnabledValue();
}
_enableViewDataDiagnostics = DataDiagnosticsSettings.GetViewEnabledValue();
_enableViewDataDiagnosticsOnLoad = _enableViewDataDiagnostics;
if (dispatcherAction != null)
{
_fileWatcher = Helper.GetFileWatcher(string.Empty, UpdatingSettings.SettingsFile, dispatcherAction);
}
// Diagnostic data retention policy
string etwDirPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys\\etw");
DeleteDiagnosticDataOlderThan28Days(etwDirPath);
InitializeLanguages();
}
@@ -196,6 +215,11 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
private bool _showWhatsNewAfterUpdatesIsGpoDisabled;
private bool _enableExperimentation;
private bool _experimentationIsGpoDisallowed;
private bool _enableDataDiagnostics;
private bool _enableDataDiagnosticsIsGpoDisallowed;
private bool _enableViewDataDiagnostics;
private bool _enableViewDataDiagnosticsOnLoad;
private bool _viewDiagnosticDataViewerChanged;
private UpdatingSettings.UpdatingState _updatingState = UpdatingSettings.UpdatingState.UpToDate;
private string _newAvailableVersion = string.Empty;
@@ -429,11 +453,74 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
}
}
public bool EnableDataDiagnostics
{
get
{
return _enableDataDiagnostics;
}
set
{
if (_enableDataDiagnostics != value)
{
_enableDataDiagnostics = value;
if (_enableDataDiagnostics == false)
{
EnableViewDataDiagnostics = false;
}
DataDiagnosticsSettings.SetEnabledValue(_enableDataDiagnostics);
NotifyPropertyChanged();
}
}
}
public bool ViewDiagnosticDataViewerChanged
{
get => _viewDiagnosticDataViewerChanged;
}
public bool EnableViewDataDiagnostics
{
get
{
return _enableViewDataDiagnostics;
}
set
{
if (_enableViewDataDiagnostics != value)
{
_enableViewDataDiagnostics = value;
if (_enableViewDataDiagnostics != _enableViewDataDiagnosticsOnLoad)
{
_viewDiagnosticDataViewerChanged = true;
}
else
{
_viewDiagnosticDataViewerChanged = false;
}
DataDiagnosticsSettings.SetViewEnabledValue(_enableViewDataDiagnostics);
OnPropertyChanged(nameof(EnableViewDataDiagnostics));
OnPropertyChanged(nameof(ViewDiagnosticDataViewerChanged));
}
}
}
public bool IsExperimentationGpoDisallowed
{
get => _experimentationIsGpoDisallowed;
}
public bool IsDataDiagnosticsGPOManaged
{
get => _enableDataDiagnosticsIsGpoDisallowed;
}
public string SettingsBackupAndRestoreDir
{
get
@@ -1129,5 +1216,54 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
SendConfigMSG(outsettings.ToString());
}
internal void RefreshSettingsOnExternalChange()
{
EnableDataDiagnostics = DataDiagnosticsSettings.GetEnabledValue();
NotifyPropertyChanged(nameof(EnableDataDiagnostics));
}
// Per retention policy
private void DeleteDiagnosticDataOlderThan28Days(string etwDirPath)
{
if (!Directory.Exists(etwDirPath))
{
return;
}
var directoryInfo = new DirectoryInfo(etwDirPath);
var cutoffDate = DateTime.Now.AddDays(-28);
foreach (var file in directoryInfo.GetFiles())
{
if (file.LastWriteTime < cutoffDate)
{
try
{
file.Delete();
}
catch (Exception ex)
{
Logger.LogError($"Failed to delete file: {file.FullName}. Error: {ex.Message}");
}
}
}
}
internal void ViewDiagnosticData()
{
string etwDirPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\PowerToys\\etw");
string tracerptPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "system32");
ETLConverter converter = new ETLConverter(etwDirPath, tracerptPath);
Task.Run(() => converter.ConvertDiagnosticsETLsAsync()).Wait();
if (Directory.Exists(etwDirPath))
{
// Open etw dir in FileExplorer
Process.Start("explorer.exe", etwDirPath);
}
}
}
}