From e1901217c68d23cb0cb7ed93b882d30a0e734ad7 Mon Sep 17 00:00:00 2001 From: Simon Mourier Date: Sat, 10 Mar 2018 14:41:18 +0100 Subject: [PATCH] Completed first verison of WpfTraceSpy. --- TraceSpyTest/Program.cs | 10 +++- WpfTraceSpy/EtwProvidersWindow.xaml | 12 ---- WpfTraceSpy/FiltersWindow.xaml | 12 ---- WpfTraceSpy/MainWindow.xaml | 2 +- WpfTraceSpy/MainWindow.xaml.cs | 92 ++++++++++++++++++++++++++++- WpfTraceSpy/WpfSettings.cs | 3 - 6 files changed, 100 insertions(+), 31 deletions(-) diff --git a/TraceSpyTest/Program.cs b/TraceSpyTest/Program.cs index 92da580..668b6dc 100644 --- a/TraceSpyTest/Program.cs +++ b/TraceSpyTest/Program.cs @@ -67,7 +67,7 @@ static void SafeMain(string[] args) var etwProvider = CommandLineUtilities.GetArgument("etw", Guid.Empty); Console.WriteLine("TraceSpy Test."); Console.WriteLine(); - Console.WriteLine("Press Q (or CTRL-C) to quit"); + Console.WriteLine("Press Q, ESC, or CTRL-C to quit"); Console.WriteLine(); Console.WriteLine("OutputDebugString"); Console.WriteLine(" Press O to send an OutputDebugString trace."); @@ -92,6 +92,9 @@ static void SafeMain(string[] args) int num = GetFinalNumber(info); switch (info.Key) { + case ConsoleKey.Escape: + return; + case ConsoleKey.Q: if (_etw != null) { @@ -119,7 +122,10 @@ static void SafeMain(string[] args) for (int i = 1; i <= num; i++) { t = "Trace #" + count + ", " + i + "/" + num + " from TraceSpyTest. Date:" + DateTime.Now; - Console.WriteLine("Sending: '" + t + "'"); + if (num < 1000 || (i % 1000) == 0) + { + Console.WriteLine("Sending: '" + t + "'"); + } _etw.WriteMessageEvent(t); count++; } diff --git a/WpfTraceSpy/EtwProvidersWindow.xaml b/WpfTraceSpy/EtwProvidersWindow.xaml index d41b2b4..df1efd6 100644 --- a/WpfTraceSpy/EtwProvidersWindow.xaml +++ b/WpfTraceSpy/EtwProvidersWindow.xaml @@ -12,18 +12,6 @@ - - - diff --git a/WpfTraceSpy/FiltersWindow.xaml b/WpfTraceSpy/FiltersWindow.xaml index 0208820..f00613a 100644 --- a/WpfTraceSpy/FiltersWindow.xaml +++ b/WpfTraceSpy/FiltersWindow.xaml @@ -12,18 +12,6 @@ - - - diff --git a/WpfTraceSpy/MainWindow.xaml b/WpfTraceSpy/MainWindow.xaml index 15e71ef..f8ede02 100644 --- a/WpfTraceSpy/MainWindow.xaml +++ b/WpfTraceSpy/MainWindow.xaml @@ -84,7 +84,7 @@ - + diff --git a/WpfTraceSpy/MainWindow.xaml.cs b/WpfTraceSpy/MainWindow.xaml.cs index bfcacd8..e9b2d5f 100644 --- a/WpfTraceSpy/MainWindow.xaml.cs +++ b/WpfTraceSpy/MainWindow.xaml.cs @@ -11,7 +11,6 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Forms; -using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Threading; @@ -30,6 +29,7 @@ public partial class MainWindow : Window private ObservableCollection _dataSource = new ObservableCollection(); private MainWindowState _state; private ConcurrentDictionary _processes = new ConcurrentDictionary(); + private Dictionary _etwListeners = new Dictionary(); private FindWindow _findWindow; private int _scrollingTo; private TraceEvent _scrollTo; @@ -126,6 +126,7 @@ private void OnStatePropertyChanged(object sender, PropertyChangedEventArgs e) protected override void OnClosed(EventArgs e) { + DisposeEtwEvents(); _findWindow?.Close(); _stopOutputDebugStringTraces = true; _outputDebugStringThread?.Join(1000); @@ -276,6 +277,7 @@ private void OdsTrace_Click(object sender, RoutedEventArgs e) private void EtwTrace_Click(object sender, RoutedEventArgs e) { _state.EtwStarted = !_state.EtwStarted; + UpdateEtwEvents(); } private string GetProcessName(int id) @@ -318,6 +320,7 @@ private void ETWProviders_Click(object sender, RoutedEventArgs e) var dlg = new EtwProvidersWindow(); dlg.Owner = this; dlg.ShowDialog(); + UpdateEtwEvents(); } private void Filters_Click(object sender, RoutedEventArgs e) @@ -463,5 +466,92 @@ private void About_Click(object sender, RoutedEventArgs e) dlg.Owner = this; dlg.ShowDialog(); } + + private void DisposeEtwEvents() + { + foreach (var kvp in _etwListeners) + { + try + { + kvp.Value.RealtimeEvent -= OnEtwListenerRealtimeEvent; + kvp.Value.Dispose(); + } + catch + { + // do nothing, continue + } + } + _etwListeners.Clear(); + } + + private void ProcessEtwTrace(object state) + { + var listener = (EventRealtimeListener)state; + listener.ProcessTraces(); + } + + private void OnEtwListenerRealtimeEvent(object sender, EventRealtimeEventArgs e) + { + var listener = (EventRealtimeListener)sender; + + var evt = new TraceEvent(); + evt.ProcessName = GetProcessName(e.ProcessId); + if (listener.Description != null && _state.ShowEtwDescription) + { + evt.ProcessName += " (" + listener.Description + ")"; + } + evt.Text = e.Message; + + ThreadPool.QueueUserWorkItem((state) => + { + Dispatcher.BeginInvoke(() => + { + AddTrace(evt); + }, DispatcherPriority.SystemIdle); + }); + } + + private void UpdateEtwEvents() + { + DisposeEtwEvents(); + if (!_state.EtwStarted) + return; + + foreach (EtwProvider provider in App.Current.Settings.EtwProviders) + { + _etwListeners.TryGetValue(provider.Guid, out EventRealtimeListener listener); + if (listener == null) + { + if (!provider.IsActive) + continue; + + // this would be a serialization bug + if (provider.Guid == Guid.Empty) + continue; + + var level = (EtwTraceLevel)provider.TraceLevel; + + listener = new EventRealtimeListener(provider.Guid, provider.Guid.ToString(), level); + listener.Description = provider.Description; + + var t = new Thread(ProcessEtwTrace); + t.Start(listener); + + listener.RealtimeEvent += OnEtwListenerRealtimeEvent; + _etwListeners.Add(provider.Guid, listener); + } + else + { + if (!provider.IsActive) + { + listener.RealtimeEvent -= OnEtwListenerRealtimeEvent; + listener.Dispose(); + _etwListeners.Remove(provider.Guid); + continue; + } + } + } + } + } } diff --git a/WpfTraceSpy/WpfSettings.cs b/WpfTraceSpy/WpfSettings.cs index fb3599a..d165676 100644 --- a/WpfTraceSpy/WpfSettings.cs +++ b/WpfTraceSpy/WpfSettings.cs @@ -26,7 +26,6 @@ public WpfSettings() RemoveEmptyLines = true; AutoScroll = true; ResolveProcessName = true; - CaptureOutputDebugString = true; Left = 50; Top = 50; FindLeft = 50; @@ -43,8 +42,6 @@ public WpfSettings() public bool ShowTooltips { get; set; } public bool ShowEtwDescription { get; set; } public bool AutoScroll { get; set; } - public bool CaptureEtwTraces { get; set; } - public bool CaptureOutputDebugString { get; set; } public bool RemoveEmptyLines { get; set; } public bool WrapText { get; set; } public int Left { get; set; }