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
6 changes: 3 additions & 3 deletions LogAnalyzerForWindows/LogAnalyzerForWindows.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
<RootNamespace>LogAnalyzerForWindows</RootNamespace>

<!-- Version Info -->
<AssemblyVersion>1.4.0.0</AssemblyVersion>
<FileVersion>1.4.0.0</FileVersion>
<InformationalVersion>1.4.0</InformationalVersion>
<AssemblyVersion>1.4.1.0</AssemblyVersion>
<FileVersion>1.4.1.0</FileVersion>
<InformationalVersion>1.4.1</InformationalVersion>

<!-- Product Info -->
<Authors>Bohdan Harabadzhyu</Authors>
Expand Down
64 changes: 59 additions & 5 deletions LogAnalyzerForWindows/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Runtime.Versioning;
using System.Diagnostics;
using System.Runtime.Versioning;
using System.Security.Principal;
using Avalonia;
using Avalonia.ReactiveUI;
using LogAnalyzerForWindows.Services;
Expand All @@ -10,13 +12,21 @@
internal sealed class Program
{
public static SingleInstanceService? SingleInstance { get; private set; }
private static bool IsElevated { get; set; }

// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args)
{
IsElevated = IsRunningAsAdmin();

if (!IsElevated && !args.Contains("--no-elevate"))
{
if (TryRestartAsAdmin())
{
return;
}
}
Comment on lines +24 to +28

Copilot AI Dec 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential infinite restart loop if elevation is required. When TryRestartAsAdmin successfully launches the elevated process and returns true, the current process exits. However, if the elevated process also fails the admin check (which shouldn't happen but could in edge cases), it would attempt to elevate again. Additionally, the --no-elevate flag is not automatically added when restarting, so if the user cancels the UAC prompt (error 1223), the application continues running without admin privileges but will attempt elevation again on next start.

Consider adding the --no-elevate flag when restarting to prevent repeated UAC prompts if the user cancels, or documenting this behavior clearly.

Copilot uses AI. Check for mistakes.

SingleInstance = new SingleInstanceService();

if (!SingleInstance.TryStart())
Expand All @@ -35,7 +45,51 @@
}
}

// Avalonia configuration, don't remove; also used by visual designer.
private static bool IsRunningAsAdmin()
{
try
{
using var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
catch

Check warning on line 56 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Code Quality & Linting

Modify 'IsRunningAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 56 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Debug)

Modify 'IsRunningAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 56 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Release)

Modify 'IsRunningAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 56 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Publish Self-Contained (win-x64)

Modify 'IsRunningAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 56 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Code Quality & Linting

Modify 'IsRunningAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 56 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Debug)

Modify 'IsRunningAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 56 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Release)

Modify 'IsRunningAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
{
return false;
}
}

private static bool TryRestartAsAdmin()
{
try
{
var exePath = Environment.ProcessPath;
if (string.IsNullOrEmpty(exePath))
{
return false;
}

var startInfo = new ProcessStartInfo
{
FileName = exePath,
UseShellExecute = true,
Verb = "runas",
Arguments = string.Join(" ", Environment.GetCommandLineArgs().Skip(1))

Copilot AI Dec 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The command-line arguments reconstruction is incorrect. Using Environment.GetCommandLineArgs().Skip(1) will skip the first argument passed to the application, not the executable path. This could lead to missing arguments when the application restarts with elevation.

For proper argument forwarding, you should either use the args parameter directly (string.Join(" ", args)) which already excludes the executable path, or if you need to handle arguments with spaces properly, use string.Join(" ", args.Select(a => a.Contains(' ') ? $""{a}"" : a)).

Copilot uses AI. Check for mistakes.
};

Process.Start(startInfo);
return true;
}
catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 1223)
{
return false;
}
catch

Check warning on line 87 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Code Quality & Linting

Modify 'TryRestartAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 87 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Debug)

Modify 'TryRestartAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 87 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Release)

Modify 'TryRestartAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 87 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Publish Self-Contained (win-x64)

Modify 'TryRestartAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 87 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Code Quality & Linting

Modify 'TryRestartAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 87 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Debug)

Modify 'TryRestartAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 87 in LogAnalyzerForWindows/Program.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Release)

Modify 'TryRestartAsAdmin' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
{
return false;
}
}

public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
Expand Down
68 changes: 63 additions & 5 deletions LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
private Axis[] _sourcesXAxes = [];
private Axis[] _sourcesYAxes = [];

private Axis[] _eventIdsXAxes = [];
private Axis[] _eventIdsYAxes = [];

public DashboardViewModel(ILogRepository repository)
{
_repository = repository ?? throw new ArgumentNullException(nameof(repository));
Expand Down Expand Up @@ -114,6 +117,18 @@
private set => SetProperty(ref _timelineYAxes, value);
}

public Axis[] EventIdsXAxes
{
get => _eventIdsXAxes;
private set => SetProperty(ref _eventIdsXAxes, value);
}

public Axis[] EventIdsYAxes
{
get => _eventIdsYAxes;
private set => SetProperty(ref _eventIdsYAxes, value);
}

public ISeries[] TopSourcesSeries
{
get => _topSourcesSeries;
Expand Down Expand Up @@ -186,6 +201,27 @@
MinLimit = 0
}
];

EventIdsYAxes =
[
new Axis
{
Labels = [],
LabelsPaint = new SolidColorPaint(SKColors.LightGray),
TextSize = 12
}
];

EventIdsXAxes =
[
new Axis
{
Name = "Count",
NamePaint = new SolidColorPaint(SKColors.White),
LabelsPaint = new SolidColorPaint(SKColors.LightGray),
MinLimit = 0
}
Comment on lines +209 to +223

Copilot AI Dec 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code duplication detected: The initialization logic for EventIds axes in the InitializeChartAxes method duplicates the same logic that will be executed in UpdateTopEventIdsChart. The axes configuration (including Name, NamePaint, LabelsPaint, MinLimit, and TextSize) is set here and then completely replaced in UpdateTopEventIdsChart when data is loaded. This creates maintainability issues as changes to axis styling need to be made in two places.

Consider removing the EventIds axes initialization from InitializeChartAxes entirely, or keeping only a minimal initialization (empty Labels array) and moving the shared configuration to a helper method that both InitializeChartAxes and UpdateTopEventIdsChart can use.

Suggested change
Labels = [],
LabelsPaint = new SolidColorPaint(SKColors.LightGray),
TextSize = 12
}
];
EventIdsXAxes =
[
new Axis
{
Name = "Count",
NamePaint = new SolidColorPaint(SKColors.White),
LabelsPaint = new SolidColorPaint(SKColors.LightGray),
MinLimit = 0
}
// Initialize with empty labels; full styling will be applied when data is loaded.
Labels = []
}
];
EventIdsXAxes =
[
// Minimal initialization; full styling will be applied when data is loaded.
new Axis()

Copilot uses AI. Check for mistakes.
];
}

public async Task LoadSessionsAsync()
Expand All @@ -206,7 +242,7 @@
SelectedSession = "All Sessions";
});
}
catch (Exception ex)

Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Code Quality & Linting

Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Debug)

Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Release)

Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Publish Self-Contained (win-x64)

Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Debug)

Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 245 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Release)

Modify 'LoadSessionsAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
{
Debug.WriteLine($"Error loading sessions: {ex.Message}");
}
Expand Down Expand Up @@ -247,7 +283,7 @@
StatusMessage = $"Dashboard loaded. Total: {stats.TotalLogs} logs";
});
}
catch (Exception ex)

Check warning on line 286 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Code Quality & Linting

Modify 'LoadDashboardDataAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 286 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Publish Self-Contained (win-x64)

Modify 'LoadDashboardDataAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 286 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Debug)

Modify 'LoadDashboardDataAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)

Check warning on line 286 in LogAnalyzerForWindows/ViewModels/DashboardViewModel.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Release)

Modify 'LoadDashboardDataAsync' to catch a more specific allowed exception type, or rethrow the exception (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1031)
{
Debug.WriteLine($"Error loading dashboard: {ex.Message}");
await Dispatcher.UIThread.InvokeAsync(() => { StatusMessage = $"Error: {ex.Message}"; });
Expand Down Expand Up @@ -363,24 +399,46 @@
if (topEventIds.Count == 0)
{
TopEventIdsSeries = [];
EventIdsYAxes = [new Axis { Labels = [] }];

Copilot AI Dec 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent axis reset behavior in empty data handling. When topEventIds.Count == 0, only EventIdsYAxes is reset but EventIdsXAxes is not. This is inconsistent with the UpdateTopSourcesChart method which doesn't reset any axes when data is empty, and also inconsistent within the same method. For consistency and to prevent displaying stale axis labels, both EventIdsXAxes and EventIdsYAxes should be reset when there's no data, similar to how both axes are updated together when data is present.

Suggested change
EventIdsYAxes = [new Axis { Labels = [] }];
EventIdsYAxes = [];
EventIdsXAxes = [];

Copilot uses AI. Check for mistakes.
return;
}

var data = topEventIds
.Select(e => new { Label = $"ID: {e.EventId}", Value = e.Count })
.ToList();
var labels = topEventIds.Select(e => $"ID: {e.EventId}").ToArray();
var values = topEventIds.Select(e => e.Count).ToArray();

TopEventIdsSeries =
[
new RowSeries<int>
{
Name = "Event Count",
Values = data.Select(d => d.Value).ToArray(),
Values = values,
Fill = new SolidColorPaint(SKColors.Coral),
Stroke = null,
MaxBarWidth = 25,
DataLabelsPaint = new SolidColorPaint(SKColors.White),
DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.End
DataLabelsPosition = LiveChartsCore.Measure.DataLabelsPosition.End,
DataLabelsFormatter = point => point.Coordinate.PrimaryValue.ToString(CultureInfo.InvariantCulture)
}
];

EventIdsYAxes =
[
new Axis
{
Labels = labels,
LabelsPaint = new SolidColorPaint(SKColors.LightGray),
TextSize = 11
}
];

EventIdsXAxes =
[
new Axis
{
Name = "Count",
NamePaint = new SolidColorPaint(SKColors.White),
LabelsPaint = new SolidColorPaint(SKColors.LightGray),
MinLimit = 0
}
];
}
Expand Down
4 changes: 3 additions & 1 deletion LogAnalyzerForWindows/Views/DashboardView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@
Foreground="White"
Margin="0,0,0,10" />
<lvc:CartesianChart Grid.Row="1"
Series="{Binding TopEventIdsSeries}" />
Series="{Binding TopEventIdsSeries}"
XAxes="{Binding EventIdsXAxes}"
YAxes="{Binding EventIdsYAxes}" />
</Grid>
</Border>
</Grid>
Expand Down
21 changes: 1 addition & 20 deletions LogAnalyzerForWindows/app.manifest
Original file line number Diff line number Diff line change
@@ -1,44 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embeded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="LogAnalyzerForWindows.Desktop"/>

<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options


<requestedExecutionLevel level="asInvoker" uiAccess="false" />
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
-->
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. -->

<!-- Windows 10 and Windows 11 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>

<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>

</assembly>
Loading