Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions global.json

This file was deleted.

2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</PropertyGroup>

<PropertyGroup>
<LangVersion>11.0</LangVersion>
<LangVersion>12.0</LangVersion>
<Features>strict</Features>
</PropertyGroup>

Expand Down
8 changes: 1 addition & 7 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>

<!-- Enable NuGet Central Package Management -->
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>

<!-- Support files and analyzers -->
<ItemGroup>
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.183" />
<PackageVersion Include="PerfView.SupportFiles" Version="1.0.8" />
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent.SupportFiles" Version="1.0.30" />
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent.AutomatedAnalysis.Analyzers" Version="0.1.2" />
</ItemGroup>

<!-- External dependencies -->
<ItemGroup>
<PackageVersion Include="Azure.Core" Version="1.38.0" />
Expand Down Expand Up @@ -41,12 +39,10 @@
<PackageVersion Include="System.Text.Json" Version="9.0.8" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
</ItemGroup>

<!-- ClrMD -->
<ItemGroup>
<PackageVersion Include="Microsoft.Diagnostics.Runtime" Version="4.0.0-beta.24314.3" />
</ItemGroup>

<!-- Test dependencies -->
<ItemGroup>
<PackageVersion Include="Microsoft.VisualStudio.Threading" Version="17.8.14" />
Expand All @@ -57,10 +53,8 @@
<PackageVersion Include="Xunit.StaFact" Version="0.3.2" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
</ItemGroup>

<!-- Sample dependencies -->
<ItemGroup>
<PackageVersion Include="System.Reactive.Linq" Version="5.0.0" />
</ItemGroup>

</Project>
22 changes: 15 additions & 7 deletions src/PerfView/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
using Microsoft.Diagnostics.Tracing;
using Microsoft.Diagnostics.Tracing.Session;
using Microsoft.Diagnostics.Utilities;

#if !PERFVIEW_COLLECT
using PerfView.Dialogs;
#endif
using PerfView.Properties;
using System;
using System.Diagnostics;
Expand Down Expand Up @@ -43,9 +47,9 @@ public static int Main(string[] args)
CommandProcessor = new CommandProcessor();
App.SetAccessibilitySwitchOverrides();

StreamWriter writerToCleanup = null; // If we create a log file, we need to clean it up.
StreamWriter writerToCleanup = null; // If we create a log file, we need to clean it up.
int retCode = -1;
bool newConsoleCreated = false; // If we create a new console, we need to wait before existing
bool newConsoleCreated = false; // If we create a new console, we need to wait before existing
try
{
#if !PERFVIEW_COLLECT
Expand Down Expand Up @@ -80,8 +84,8 @@ public static int Main(string[] args)
DisplaySplashScreen();
}
#endif
App.Unpack(); // Install the program if it is not done already
App.RelaunchIfNeeded(args); // If we are running from a a network share, relaunch locally.
App.Unpack(); // Install the program if it is not done already
App.RelaunchIfNeeded(args); // If we are running from a a network share, relaunch locally.

// This does the real work
retCode = DoMain(args, ref newConsoleCreated, ref writerToCleanup);
Expand Down Expand Up @@ -891,10 +895,13 @@ public static SymbolReader GetSymbolReader(string etlFilePath = null, SymbolRead
#if !PERFVIEW_COLLECT
if (!App.CommandLineArgs.TrustPdbs)
{
ret.SecurityCheck = delegate (string pdbFile)
ret.SecurityCheck = pdbFile =>
{
var result = System.Windows.MessageBox.Show("Found " + pdbFile + " on your local machine. Do you want to use it?",
"Security Check", System.Windows.MessageBoxButton.YesNo);
var result = XamlMessageBox.Show(
$"Found {pdbFile} on your local machine. Do you want to use it?",
"Security Check",
System.Windows.MessageBoxButton.YesNo);

return result == System.Windows.MessageBoxResult.Yes;
};
}
Expand Down Expand Up @@ -1265,6 +1272,7 @@ protected override void Dispose(bool disposing)
m_terseLog.Dispose();
m_verboseLog.Dispose();
}

#region private
private TextWriter m_verboseLog;
private TextWriter m_terseLog;
Expand Down
31 changes: 18 additions & 13 deletions src/PerfView/CommandProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
using Microsoft.Diagnostics.Tracing.Session;
using Microsoft.Diagnostics.Utilities;
using Microsoft.Win32;
#if !PERFVIEW_COLLECT
using PerfView.Dialogs;
#endif
using System;
using System.Collections.Generic;
using System.Diagnostics;
Expand All @@ -17,7 +20,6 @@
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Triggers;
using Utilities;
using Trigger = Triggers.Trigger;
Expand Down Expand Up @@ -1682,16 +1684,19 @@ internal static void UnZipIfNecessary(ref string inputFileName, TextWriter log,
private void InformedAboutSkippingMerge()
{
#if !PERFVIEW_COLLECT
GuiApp.MainWindow.Dispatcher.BeginInvoke((Action)delegate ()
GuiApp.MainWindow.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(GuiApp.MainWindow,
"If you are analyzing the data on the same machine on which you collected it, in the future " +
"you can avoid the time it takes to merge and zip the file by unchecking the 'merge' checkbox " +
"on the collection dialog box.\r\n\r\n" +
"Be careful however, PerfView will remember this option from run to run and you will have to " +
"either check the zip checkbox or use the PerfView's zip command if you wish to analyze on another machine.\r\n\r\n" +
"The WPA analyzer requires merging unconditionally, so you must merge if you wish to use that tool.\r\n\n" +
"See the 'Merging' section in the users guide for complete details.",
XamlMessageBox.Show(
GuiApp.MainWindow,
"""
If you are analyzing the data on the same machine on which you collected it, in the future you can avoid the time it takes to merge and zip the file by unchecking the 'merge' checkbox on the collection dialog box.

Be careful however, PerfView will remember this option from run to run and you will have to either check the zip checkbox or use the PerfView's zip command if you wish to analyze on another machine.

The WPA analyzer requires merging unconditionally, so you must merge if you wish to use that tool.

See the 'Merging' section in the users guide for complete details.
""",
"Skip Merging/Zipping for faster local processing.");
});
#endif
Expand Down Expand Up @@ -3306,11 +3311,11 @@ private void ShowAspNetWarningBox(string message)
{
#if !PERFVIEW_COLLECT
// Are we activating with the GUI, then pop a dialog box
if (App.CommandLineArgs.LogFile == null && GuiApp.MainWindow != null)
if (App.CommandLineArgs.LogFile is null)
{
GuiApp.MainWindow.Dispatcher.BeginInvoke((Action)delegate ()
GuiApp.MainWindow?.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(GuiApp.MainWindow, message, "Warning ASP.NET Tracing not installed");
XamlMessageBox.Show(GuiApp.MainWindow, message, "Warning ASP.NET Tracing not installed");
});
}
#endif
Expand Down
67 changes: 67 additions & 0 deletions src/PerfView/Dialogs/ImageHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Windows.Win32.UI.WindowsAndMessaging;
using Windows.Win32.Foundation;
using Windows.Win32.UI.Shell;
using System.Windows.Interop;
using System.Runtime.CompilerServices;
using System;

namespace PerfView.Dialogs;

internal static class ImageHelpers
{
/// <summary>
/// Gets the <see cref="ImageSource"/> for the specified <see cref="MessageBoxImage"/>.
/// </summary>
/// <remarks>
/// <para>
/// This method reurns the modern version of the stock icons used in message boxes.
/// </para>
/// </remarks>
public static ImageSource ToImageSource(MessageBoxImage image) => image switch
{
MessageBoxImage.Error => GetStockIcon(SHSTOCKICONID.SIID_ERROR),
MessageBoxImage.Information => GetStockIcon(SHSTOCKICONID.SIID_INFO),
MessageBoxImage.Warning => GetStockIcon(SHSTOCKICONID.SIID_WARNING),
MessageBoxImage.Question => GetStockIcon(SHSTOCKICONID.SIID_HELP),
_ => throw new ArgumentOutOfRangeException(nameof(image)),
};

private static unsafe ImageSource GetStockIcon(SHSTOCKICONID stockIcon, SHGSI_FLAGS options = default)
{
// Note that we don't explicitly check for invalid StockIconId to allow for accessing newer ids introduced
// in later OSes. The HRESULT returned for undefined ids gets converted to an ArgumentException.

SHSTOCKICONINFO info = new()
{
cbSize = (uint)Unsafe.SizeOf<SHSTOCKICONINFO>(),
};

HRESULT result = SHGetStockIconInfo(stockIcon, options | SHGSI_FLAGS.SHGSI_ICON, &info);

// This only throws if there is an error.
Marshal.ThrowExceptionForHR((int)result);

return Imaging.CreateBitmapSourceFromHIcon(info.hIcon, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
}

// This can't be imported in CsWin32 as it technically isn't the same on both X86 and X64 due to a packing of 1 byte on X86.
// For our purposes this is fine as the single definition's layout (SHSTOCKICONINFO) is the same on both platforms.

[DllImport("Shell32.dll", ExactSpelling = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
private static extern unsafe HRESULT SHGetStockIconInfo(SHSTOCKICONID siid, SHGSI_FLAGS uFlags, SHSTOCKICONINFO* psii);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private unsafe struct SHSTOCKICONINFO
{
public uint cbSize;
public HICON hIcon;
public int iSysImageIndex;
public int iIcon;
public fixed char szPath[260];
}
}
2 changes: 1 addition & 1 deletion src/PerfView/Dialogs/ManagePresetsDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private void SaveClicked(object sender, RoutedEventArgs e)
{
if (Presets.Exists(x => x.Name == PresetName.Text))
{
MessageBox.Show(
XamlMessageBox.Show(
$"Preset '{PresetName.Text}' already exists. Choose another name.",
"Preset Name",
MessageBoxButton.OK,
Expand Down
11 changes: 8 additions & 3 deletions src/PerfView/Dialogs/MemoryDataDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,15 @@ private void DumpHeap(bool closeOnComplete)

if (m_args.MaxDumpCountK >= 10000)
{
var response = MessageBox.Show("WARNING: you have selected a Max Dump Count larger than 10M objects.\r\n" +
"You should only need 100K to do a good job, even at 10M the GUI will be very sluggish.\r\n" +
"Consider canceling and picking a smaller value.", "Max Dump Size Too Big",
var response = XamlMessageBox.Show(
"""
WARNING: you have selected a Max Dump Count larger than 10M objects.
You should only need 100K to do a good job, even at 10M the GUI will be very sluggish.
Consider canceling and picking a smaller value.
""",
"Max Dump Size Too Big",
MessageBoxButton.OKCancel);

if (response != MessageBoxResult.OK)
{
StatusBar.Log("Memory collection canceled.");
Expand Down
51 changes: 51 additions & 0 deletions src/PerfView/Dialogs/MessageBoxWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<Window x:Class="PerfView.Dialogs.MessageBoxWindow"
x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WPFToolKit="http://schemas.microsoft.com/wpf/2008/toolkit"
xmlns:src="clr-namespace:PerfView"
Title="MessageBoxWindow"
Width="480"
MinHeight="180"
MinWidth="480"
SizeToContent="Height"
WindowStartupLocation="CenterOwner">
<Window.Style>
<Style TargetType="Window" BasedOn="{StaticResource CustomToolWindowStyle}">
<Setter Property="WindowStyle" Value="ToolWindow"/>
<Setter Property="ResizeMode" Value="NoResize"/>
<Setter Property="ShowInTaskbar" Value="False"/>
<Setter Property="Icon" Value="{x:Null}"/>
</Style>
</Window.Style>
<DockPanel LastChildFill="True">
<!-- Button area docked to bottom -->
<Border DockPanel.Dock="Bottom"
Height="60"
Background="{StaticResource ControlDarkerBackground}"
BorderBrush="{StaticResource ControlDefaultBorderBrush}"
Padding="0,10">
<StackPanel x:Name="ButtonsPanel" Orientation="Horizontal" HorizontalAlignment="Right" Margin="20,0">
<StackPanel.Resources>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin" Value="5,0"/>
<Setter Property="Padding" Value="5,0"/>
<Setter Property="MinWidth" Value="95"/>
<Setter Property="Height" Value="30"/>
</Style>
</StackPanel.Resources>
</StackPanel>
</Border>
<!-- Message content area fills the rest -->
<DockPanel Margin="15,30">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image x:Name="IconImage" Width="32" Height="32" Margin="15,0" VerticalAlignment="Top"/>
<TextBlock x:Name="MessageTextBlock" Grid.Column="1" TextWrapping="Wrap" VerticalAlignment="Top"/>
</Grid>
</DockPanel>
</DockPanel>
</Window>
Loading