mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
[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:
102
src/settings-ui/Settings.UI/Helpers/ETLConverter.cs
Normal file
102
src/settings-ui/Settings.UI/Helpers/ETLConverter.cs
Normal 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}.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
src/settings-ui/Settings.UI/Helpers/NativeEventWaiter.cs
Normal file
30
src/settings-ui/Settings.UI/Helpers/NativeEventWaiter.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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=}"
|
||||
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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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="" />
|
||||
</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=,
|
||||
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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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=}"
|
||||
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=}"
|
||||
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=}"
|
||||
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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 & 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 & 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 & feedback</value>
|
||||
</data>
|
||||
<data name="GeneralPage_DiagnosticsAndFeedback_Link.Content" xml:space="preserve">
|
||||
<value>Learn more about the information we log & 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>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user