Skip to content

Commit 7667962

Browse files
committed
add detailed log view
1 parent f3dae6e commit 7667962

9 files changed

+253
-37
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<Window xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:vm="using:WEventViewer.ViewModel"
6+
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
7+
MinHeight="400"
8+
MinWidth="500"
9+
x:Class="WEventViewer.DetailedLogMessageWIndow"
10+
x:DataType="vm:DetailedLogViewModel"
11+
Title="DetailedLogMessageWIndow">
12+
<Design.DataContext>
13+
<vm:DetailedLogViewModel></vm:DetailedLogViewModel>
14+
</Design.DataContext>
15+
<Grid>
16+
<Grid.RowDefinitions>
17+
<RowDefinition Height="*"></RowDefinition>
18+
<RowDefinition Height="Auto"></RowDefinition>
19+
</Grid.RowDefinitions>
20+
<TabControl Margin="10" Grid.Row="0">
21+
<TabItem Header="Properties">
22+
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
23+
<DataGrid Margin="10"
24+
IsReadOnly="True"
25+
ItemsSource="{Binding Items}"
26+
BorderThickness="1"
27+
GridLinesVisibility="Horizontal"
28+
HeadersVisibility="Column"
29+
CanUserReorderColumns="True"
30+
CanUserResizeColumns="True"
31+
AutoGenerateColumns="True"
32+
>
33+
34+
</DataGrid>
35+
<!--<Grid Margin="10">
36+
<Grid.ColumnDefinitions>
37+
<ColumnDefinition Width="Auto"/>
38+
<ColumnDefinition Width="*"/>
39+
</Grid.ColumnDefinitions>
40+
<Grid.RowDefinitions>
41+
<RowDefinition Height="Auto"/>
42+
<RowDefinition Height="Auto"/>
43+
<RowDefinition Height="Auto"/>
44+
<RowDefinition Height="Auto"/>
45+
<RowDefinition Height="Auto"/>
46+
<RowDefinition Height="Auto"/>
47+
</Grid.RowDefinitions>
48+
<Label Content="TimeCreated" Grid.Column="0" Grid.Row="0"/>
49+
<TextBlock Text="{Binding TimeCreated}" Grid.Column="1" Grid.Row="0"/>
50+
<Label Content="Level" Grid.Column="0" Grid.Row="1"/>
51+
<TextBlock Text="{Binding LevelDisplayName}" Grid.Column="1" Grid.Row="1"/>
52+
<Label Content="LogName" Grid.Column="0" Grid.Row="2"/>
53+
<TextBlock Text="{Binding LogName}" Grid.Column="1" Grid.Row="2"/>
54+
--><!--<StackPanel Orientation="Horizontal" Margin="10">
55+
</StackPanel>
56+
<StackPanel Orientation="Horizontal" Margin="10">
57+
<Label Content="LogName"/>
58+
<TextBlock Text="{Binding LogName}"/>
59+
</StackPanel>
60+
<StackPanel Orientation="Horizontal" Margin="10">
61+
<Label Content="ProviderName"/>
62+
<TextBlock Text="{Binding ProviderName}"/>
63+
</StackPanel>
64+
<StackPanel Orientation="Horizontal" Margin="10">
65+
<Label Content="FormattedString"/>
66+
<TextBlock Text="{Binding FormattedString}"/>
67+
</StackPanel>--><!--
68+
</Grid>-->
69+
</ScrollViewer>
70+
</TabItem>
71+
<TabItem Header="XML">
72+
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
73+
<TextBlock Text="{Binding XmlString,Mode=OneTime}" Margin="10"/>
74+
</ScrollViewer>
75+
</TabItem>
76+
</TabControl>
77+
<Button Grid.Row="1" Content="Close" HorizontalAlignment="Right" Margin="10" Click="OnCloseClicked"/>
78+
</Grid>
79+
</Window>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Avalonia.Controls;
2+
using Avalonia.Interactivity;
3+
4+
namespace WEventViewer
5+
{
6+
public partial class DetailedLogMessageWIndow : Window
7+
{
8+
public DetailedLogMessageWIndow()
9+
{
10+
InitializeComponent();
11+
}
12+
void OnCloseClicked(object? sender, RoutedEventArgs routedEventArgs)
13+
{
14+
this.Close();
15+
}
16+
}
17+
}

src/WEventViewer/MainWindow.axaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@
2727
BorderBrush="Black"
2828
Margin="20"
2929
BorderThickness="1"
30-
IsReadOnly="True" ItemsSource="{Binding LogRecords}" VerticalAlignment="Stretch" MinHeight="200" Height="{Binding LogViewMaxHeight,Mode=OneWay}">
30+
IsReadOnly="True"
31+
ItemsSource="{Binding LogRecords}"
32+
VerticalAlignment="Stretch" MinHeight="200"
33+
Height="{Binding LogViewMaxHeight,Mode=OneWay}"
34+
DoubleTapped="DataGrid_DoubleTapped_1">
3135
<DataGrid.Columns>
36+
3237
<DataGridTextColumn Header="TimeCreated" Binding="{Binding TimeCreated}"/>
3338
<DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
3439
<DataGridTextColumn Header="LogName" Binding="{Binding LogName}"/>

src/WEventViewer/MainWindow.axaml.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
using Avalonia.Controls;
22
using CommunityToolkit.Mvvm.Input;
33
using CommunityToolkit.Mvvm.Messaging;
4+
using System.Diagnostics;
5+
using WEventViewer.Model;
46
using WEventViewer.ViewModel;
57

68
namespace WEventViewer;
79

810
internal record class OpenErrorLogWindow(string message);
911
public partial class MainWindow : Window
1012
{
13+
DiagnosticListener _DS = new DiagnosticListener(nameof(MainWindow));
1114
public MainWindow()
1215
{
1316
DataContext = new MainWindowViewModel();
@@ -41,4 +44,21 @@ private void Window_SizeChanged(object? sender, Avalonia.Controls.SizeChangedEve
4144
mwvm.CurrentWindowHeight = this.Height;
4245
}
4346
}
47+
48+
private async void DataGrid_DoubleTapped_1(object? sender, Avalonia.Input.TappedEventArgs e)
49+
{
50+
_DS.Write("OnDataGridDoubleTapped", e);
51+
if(sender is DataGrid dataGrid)
52+
{
53+
if (dataGrid.SelectedItem is LogRecord record)
54+
{
55+
var vm = new DetailedLogViewModel(record);
56+
var w = new DetailedLogMessageWIndow()
57+
{
58+
DataContext = vm,
59+
};
60+
await w.ShowDialog(this);
61+
}
62+
}
63+
}
4464
}

src/WEventViewer/Model/EventLogRepository.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ internal record class LogRecord(Guid? ActivityId,
3636
int? ThreadId,
3737
DateTime? TimeCreated,
3838
byte? Version,
39-
string Formatted);
39+
string Formatted,
40+
string XmlString);
4041
internal static class EventLogRepositoryExtension
4142
{
4243
static readonly DiagnosticListener _DS = new DiagnosticListener(nameof(EventLogRepositoryExtension));
@@ -51,7 +52,7 @@ public static LogRecord ToLogRecord(this EventRecord record)
5152
return new LogRecord(record.ActivityId, record.Id, keywords, keywordDisplayNames, record.Level,
5253
levelName, record.LogName, record.MachineName, record.Opcode, opcodeDisplayName, record.ProcessId,
5354
record.Properties.Select(x => x.Value).ToArray(), record.ProviderId, record.ProviderName, record.Qualifiers, record.RecordId, record.RelatedActivityId,
54-
record.Task, taskDisplayName, record.ThreadId, record.TimeCreated, record.Version, record.FormatDescription());
55+
record.Task, taskDisplayName, record.ThreadId, record.TimeCreated, record.Version, record.FormatDescription(), record.ToXml());
5556
}
5657
static string[] GetKeywordsDisplayNames(EventRecord record)
5758
{

src/WEventViewer/OpenLogWindow.axaml

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
55
xmlns:vm="using:WEventViewer.ViewModel"
66
xmlns:local="using:WEventViewer"
7-
mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="350"
7+
mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="500"
88
x:Class="WEventViewer.OpenLogWindow"
99
x:DataType="vm:OpenLogWindowViewModel"
1010
Title="OpenLogWindow">
@@ -16,50 +16,68 @@
1616
</Window.Resources>
1717
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="20">
1818
<Grid.RowDefinitions>
19-
<RowDefinition Height="*"></RowDefinition>
20-
<RowDefinition Height="*"></RowDefinition>
2119
<RowDefinition Height="*"></RowDefinition>
2220
<RowDefinition Height="Auto"></RowDefinition>
2321
</Grid.RowDefinitions>
24-
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Grid.Row="0" VerticalAlignment="Center">
25-
<Label Content="LogName"
26-
Margin="10,10,10,10"
27-
HorizontalAlignment="Left"
28-
VerticalAlignment="Center"
22+
<StackPanel Margin="10" Orientation="Vertical" Grid.Row="0">
23+
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Grid.Row="0" VerticalAlignment="Center">
24+
<Label Content="LogName"
25+
Margin="10,10,10,10"
26+
HorizontalAlignment="Left"
27+
VerticalAlignment="Center"
2928
/>
30-
<TextBox HorizontalContentAlignment="Left"
31-
VerticalContentAlignment="Center"
32-
TextAlignment="Left"
33-
Margin="10,10,10,10"
34-
HorizontalAlignment="Right"
35-
Text="{Binding LogName, Mode=TwoWay}"
36-
MinWidth="200" MaxWidth="1000"
29+
<TextBox HorizontalContentAlignment="Left"
30+
VerticalContentAlignment="Center"
31+
TextAlignment="Left"
32+
Margin="10,10,10,10"
33+
HorizontalAlignment="Right"
34+
Text="{Binding LogName, Mode=TwoWay}"
35+
MinWidth="200" MaxWidth="1000"
3736
/>
38-
</StackPanel>
39-
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Grid.Row="1" VerticalAlignment="Center">
40-
<Label Content="PathType"
41-
Margin="10,10,10,10"
42-
HorizontalAlignment="Left"
43-
VerticalAlignment="Center"/>
44-
<!--<TextBox Margin="10,10,10,10"
37+
</StackPanel>
38+
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" Grid.Row="1" VerticalAlignment="Center">
39+
<Label Content="PathType"
40+
Margin="10,10,10,10"
41+
HorizontalAlignment="Left"
42+
VerticalAlignment="Center"/>
43+
<!--<TextBox Margin="10,10,10,10"
4544
HorizontalAlignment="Stretch"
4645
TextAlignment="Left"
4746
VerticalContentAlignment="Center"
4847
Text="{Binding Path=PathType, Mode=TwoWay,Converter={StaticResource PathTypeConverter}}"/>-->
49-
<ComboBox
50-
HorizontalAlignment="Stretch"
51-
Margin="10"
52-
ItemsSource="{Binding PathTypes}"
53-
SelectedValue="{Binding CurrentSelected}"
48+
<ComboBox
49+
HorizontalAlignment="Stretch"
50+
Margin="10"
51+
ItemsSource="{Binding PathTypes}"
52+
SelectedValue="{Binding CurrentSelected}"
5453
>
55-
<ComboBox.ItemTemplate>
56-
<DataTemplate>
57-
<Label Content="{Binding DisplayName}"/>
58-
</DataTemplate>
59-
</ComboBox.ItemTemplate>
60-
</ComboBox>
54+
<ComboBox.ItemTemplate>
55+
<DataTemplate>
56+
<Label Content="{Binding DisplayName}"/>
57+
</DataTemplate>
58+
</ComboBox.ItemTemplate>
59+
</ComboBox>
60+
</StackPanel>
61+
<Expander Header="Advanced" Grid.Row="2" HorizontalAlignment="Stretch" MaxHeight="300">
62+
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
63+
<StackPanel Orientation="Vertical" MaxHeight="500">
64+
<CheckBox Name="UseRawQuery" Content="raw query" Margin="10"/>
65+
<TextBox Name="RawQueryInput" Margin="10"/>
66+
<Border BorderThickness="1" BorderBrush="Gray"/>
67+
<CheckBox Name="UseTimeCreated" Content="show ranged time"/>
68+
<StackPanel Orientation="Vertical">
69+
<Label Content="Since:"/>
70+
<DatePicker Name="BeginDate"/>
71+
<TimePicker/>
72+
<Label Content="Until:"/>
73+
<DatePicker Name="EndDate"/>
74+
<TimePicker/>
75+
</StackPanel>
76+
</StackPanel>
77+
</ScrollViewer>
78+
</Expander>
6179
</StackPanel>
62-
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="2" VerticalAlignment="Bottom">
80+
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Grid.Row="1" VerticalAlignment="Bottom">
6381
<Button Content="OK" Command="{ Binding OkCommand }" Margin="10" Padding="10"/>
6482
<Button Content="Cancel" Command="{ Binding CancelCommand }" Margin="10" Padding="10"/>
6583
</StackPanel>
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
using System.Threading.Tasks;
8+
using System.Xml;
9+
using System.Xml.Linq;
10+
using WEventViewer.Model;
11+
12+
namespace WEventViewer.ViewModel
13+
{
14+
internal class DetailedLogViewModel : INotifyPropertyChanged
15+
{
16+
public DetailedLogViewModel() : this(null)
17+
{
18+
}
19+
LogRecord? logRecord;
20+
21+
public event PropertyChangedEventHandler? PropertyChanged;
22+
23+
public DetailedLogViewModel(LogRecord? logRecord)
24+
{
25+
this.logRecord = logRecord;
26+
if (logRecord != null && !string.IsNullOrEmpty(logRecord.XmlString))
27+
{
28+
var doc = XDocument.Parse(logRecord.XmlString);
29+
using var tw = new StringWriter();
30+
using var xw = new XmlTextWriter(tw);
31+
xw.Formatting = Formatting.Indented;
32+
doc.WriteTo(xw);
33+
_FormattedXmlString = tw.ToString();
34+
}
35+
if(logRecord != null)
36+
{
37+
Items = new KeyValuePair<string, string?>[]
38+
{
39+
new("Id", logRecord.Id.ToString()),
40+
new("RecordId", logRecord.RecordId?.ToString()),
41+
new("ActivityId", logRecord.ActivityId?.ToString()),
42+
new("LogName", logRecord.LogName),
43+
new("MachineName", logRecord.MachineName),
44+
new("Level", string.IsNullOrEmpty(logRecord.LevelDisplayName) ? logRecord.Level?.ToString() : logRecord.LevelDisplayName),
45+
new("TimeCreated", logRecord.TimeCreated?.ToString("o")),
46+
new("ProviderName", logRecord.ProviderName),
47+
new("OpCode", logRecord.OpCode?.ToString("x")),
48+
new("Keywords", logRecord.Keywords?.ToString("x")),
49+
new("Tasks", logRecord.Task?.ToString("x")),
50+
new("Qualifiers", logRecord.Qualifiers?.ToString("x")),
51+
new("Description", logRecord.Formatted),
52+
};
53+
}
54+
}
55+
public KeyValuePair<string, string?>[] Items { get; private set; } = Array.Empty<KeyValuePair<string, string?>>();
56+
string _FormattedXmlString;
57+
public string XmlString => _FormattedXmlString;
58+
public string? FormattedString => logRecord?.Formatted;
59+
public DateTime? TimeCreated => logRecord?.TimeCreated;
60+
public long? Keywords => logRecord?.Keywords;
61+
public byte? Level => logRecord?.Level;
62+
public string? LevelDisplayName => logRecord?.LevelDisplayName;
63+
public string? LogName => logRecord?.LogName;
64+
public string? MachineName => logRecord?.MachineName;
65+
public short? OpCode => logRecord?.OpCode;
66+
public int? ProcessId => logRecord?.ProcessId;
67+
public long? RecordId => logRecord?.RecordId;
68+
public string? ProviderName => logRecord?.ProviderName;
69+
}
70+
}

src/WEventViewer/ViewModel/MainWindowViewModel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using System.ComponentModel;
1919
using System.Security.Cryptography.X509Certificates;
2020
using Avalonia.Threading;
21+
using Avalonia.Input;
2122

2223

2324
namespace WEventViewer.ViewModel
@@ -29,6 +30,7 @@ class OpenLogRequest
2930
}
3031
record class LoadLogMessage(string logName, PathType pathType);
3132
record class MainWindowCloseMessage();
33+
record class OpenDetailedLogMessage();
3234
internal class MainWindowViewModel : ObservableRecipient
3335
{
3436
EventLogRepository _EventLogRepository;

src/WEventViewer/WEventViewer.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,8 @@
2121
<PackageReference Include="R3Extensions.Avalonia" Version="1.1.13" />
2222
<PackageReference Include="System.Diagnostics.EventLog" Version="8.0.0" />
2323
</ItemGroup>
24+
25+
<ItemGroup>
26+
<UpToDateCheckInput Remove="DetailedLogMessageWIndow.axaml" />
27+
</ItemGroup>
2428
</Project>

0 commit comments

Comments
 (0)