From f0dcad22ff2c21b282f0e3042b5b4cb898623e10 Mon Sep 17 00:00:00 2001 From: EonaCat <EonaCat@gmail.com> Date: Thu, 27 Mar 2025 19:48:21 +0100 Subject: [PATCH] Updated colors --- .../ConnectionDetailsWindow.xaml | 2 + .../ConnectionDetailsWindow.xaml.cs | 24 +- EonaCat.PortMonitor/ConnectionInfo.cs | 43 +++ EonaCat.PortMonitor/MainWindow.xaml | 20 +- EonaCat.PortMonitor/MainWindow.xaml.cs | 281 ++++++++++-------- 5 files changed, 242 insertions(+), 128 deletions(-) create mode 100644 EonaCat.PortMonitor/ConnectionInfo.cs diff --git a/EonaCat.PortMonitor/ConnectionDetailsWindow.xaml b/EonaCat.PortMonitor/ConnectionDetailsWindow.xaml index 8d35b5e..3cba429 100644 --- a/EonaCat.PortMonitor/ConnectionDetailsWindow.xaml +++ b/EonaCat.PortMonitor/ConnectionDetailsWindow.xaml @@ -29,6 +29,7 @@ <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> + <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> @@ -75,6 +76,7 @@ <TextBlock Text="Connection duration:" FontSize="14" Foreground="{DynamicResource DynamicTextColor}" VerticalAlignment="Center" Grid.Row="9" Grid.Column="0" Margin="0,5"/> <TextBox Name="ConnectionDurationText" FontSize="14" Foreground="{DynamicResource DynamicTextColor}" VerticalAlignment="Center" Grid.Row="9" Grid.Column="2" Margin="0,5" IsReadOnly="True" Background="Transparent" BorderBrush="Transparent"/> + <Button x:Name="btnProcessPath" Content="Open Process Path" FontSize="14" Foreground="{DynamicResource DynamicTextColor}" VerticalAlignment="Center" Grid.Row="10" Grid.Column="0" Grid.ColumnSpan="3" Margin="0,10" Click="btnProcessPath_Click"/> </Grid> </Border> </Grid> diff --git a/EonaCat.PortMonitor/ConnectionDetailsWindow.xaml.cs b/EonaCat.PortMonitor/ConnectionDetailsWindow.xaml.cs index 2c1c7f9..b2a7b9d 100644 --- a/EonaCat.PortMonitor/ConnectionDetailsWindow.xaml.cs +++ b/EonaCat.PortMonitor/ConnectionDetailsWindow.xaml.cs @@ -1,4 +1,6 @@ -using System.Windows; +using System.Diagnostics; +using System.Windows; +using MessageBox = System.Windows.MessageBox; namespace EonaCat.PortMonitor { @@ -7,10 +9,13 @@ namespace EonaCat.PortMonitor /// </summary> public partial class ConnectionDetailsWindow : Window { + private ConnectionInfo _currentConnection; + public ConnectionDetailsWindow(ConnectionInfo conn) { InitializeComponent(); + _currentConnection = conn; ProtocolText.Text = conn.Protocol; LocalAddressText.Text = conn.LocalAddress; LocalPortText.Text = conn.LocalPort.ToString(); @@ -45,5 +50,22 @@ namespace EonaCat.PortMonitor { Dispatcher.Invoke(() => ConnectionDurationText.Text = Convert.ToString(conn.FormattedConnectionDuration)); } + + private void btnProcessPath_Click(object sender, RoutedEventArgs e) + { + // Open the process path in explorer + try + { + var process = Process.GetProcessById(_currentConnection.ProcessId); + if (process != null && process.MainModule != null) + { + Process.Start("explorer.exe", $"/select, \"{process.MainModule.FileName}\""); + } + } + catch (Exception ex) + { + MessageBox.Show($"Failed to get process path: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + } } } diff --git a/EonaCat.PortMonitor/ConnectionInfo.cs b/EonaCat.PortMonitor/ConnectionInfo.cs new file mode 100644 index 0000000..9210e2b --- /dev/null +++ b/EonaCat.PortMonitor/ConnectionInfo.cs @@ -0,0 +1,43 @@ +using System.ComponentModel; + +namespace EonaCat.PortMonitor +{ + public class ConnectionInfo : INotifyPropertyChanged + { + private System.Windows.Media.SolidColorBrush _connectionColor; + + public string Protocol { get; set; } + public string LocalAddress { get; set; } + public int LocalPort { get; set; } + public string RemoteAddress { get; set; } + public int RemotePort { get; set; } + public string State { get; set; } + public int ProcessId { get; set; } + public string ProcessName { get; set; } + public DateTime ConnectionTime { get; set; } + public DateTime FirstConnectionTime { get; set; } + public string ConnectionStatus { get; set; } + public TimeSpan ConnectionDuration => DateTime.Now - FirstConnectionTime; + public string FormattedConnectionDuration => ConnectionDuration.ToString(@"hh\:mm\:ss"); + + public System.Windows.Media.SolidColorBrush ConnectionColor + { + get { return _connectionColor; } + set + { + if (_connectionColor != value) + { + _connectionColor = value; + OnPropertyChanged(nameof(ConnectionColor)); + } + } + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/EonaCat.PortMonitor/MainWindow.xaml b/EonaCat.PortMonitor/MainWindow.xaml index cf093bc..5ba8865 100644 --- a/EonaCat.PortMonitor/MainWindow.xaml +++ b/EonaCat.PortMonitor/MainWindow.xaml @@ -1,7 +1,7 @@ <Window x:Class="EonaCat.PortMonitor.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - Title="EonaCat Port Monitor" Height="600" Width="1500" WindowStartupLocation="CenterScreen"> + Title="EonaCat Port Monitor" Height="600" Width="1600" WindowStartupLocation="CenterScreen"> <Window.Resources> <ResourceDictionary Source="/Themes.xaml" /> @@ -43,8 +43,13 @@ <TabControl Margin="10" Grid.Row="2" > <TabItem Header="Connections" > <DataGrid Name="NetworkDataGrid" AutoGenerateColumns="False" IsReadOnly="True" Margin="10" PreviewMouseDoubleClick="DataGrid_PreviewMouseDoubleClick"> + <DataGrid.CellStyle> + <Style TargetType="DataGridCell"> + <Setter Property="Background" Value="{Binding ConnectionColor}" /> + </Style> + </DataGrid.CellStyle> <DataGrid.Columns> - <DataGridTextColumn Header="Protocol" Binding="{Binding Protocol}" Width="100"/> + <DataGridTextColumn Header="Protocol" Binding="{Binding Protocol}" Width="100" /> <DataGridTextColumn Header="Local Address" Binding="{Binding LocalAddress}" Width="200"/> <DataGridTextColumn Header="Local Port" Binding="{Binding LocalPort}" Width="100"/> <DataGridTextColumn Header="Remote Address" Binding="{Binding RemoteAddress}" Width="200"/> @@ -58,6 +63,11 @@ </TabItem> <TabItem Header="Inbound Connections" > <DataGrid Name="InboundDataGrid" AutoGenerateColumns="False" IsReadOnly="True" Margin="10" PreviewMouseDoubleClick="DataGrid_PreviewMouseDoubleClick"> + <DataGrid.CellStyle> + <Style TargetType="DataGridCell"> + <Setter Property="Background" Value="{Binding ConnectionColor}" /> + </Style> + </DataGrid.CellStyle> <DataGrid.Columns> <DataGridTextColumn Header="Protocol" Binding="{Binding Protocol}" Width="100"/> <DataGridTextColumn Header="Local Address" Binding="{Binding LocalAddress}" Width="200"/> @@ -73,6 +83,11 @@ </TabItem> <TabItem Header="Outbound Connections" > <DataGrid Name="OutboundDataGrid" AutoGenerateColumns="False" IsReadOnly="True" Margin="10" PreviewMouseDoubleClick="DataGrid_PreviewMouseDoubleClick"> + <DataGrid.CellStyle> + <Style TargetType="DataGridCell"> + <Setter Property="Background" Value="{Binding ConnectionColor}" /> + </Style> + </DataGrid.CellStyle> <DataGrid.Columns> <DataGridTextColumn Header="Protocol" Binding="{Binding Protocol}" Width="100"/> <DataGridTextColumn Header="Local Address" Binding="{Binding LocalAddress}" Width="200"/> @@ -96,6 +111,7 @@ <Button Content="Export to HTML" Width="120" Height="30" Margin="10,0" VerticalAlignment="Center" Click="ExportToHtmlButton_Click" /> <Button Content="Save Filter Preset" Width="120" Height="30" Margin="10,0" VerticalAlignment="Center" Click="SaveFilterPresetButton_Click" /> <Button Content="Load Filter Preset" Width="120" Height="30" Margin="10,0" VerticalAlignment="Center" Click="LoadFilterPresetButton_Click" /> + <Button Content="Open Process Path" Width="120" Height="30" Margin="10,0" VerticalAlignment="Center" Click="ProcessPathButton_Click" /> <Button Content="Kill Process" Width="120" Height="30" Margin="10,0" VerticalAlignment="Center" Click="KillProcessButton_Click" /> <Button Content="IP Lookup" Width="120" Height="30" Margin="10,0" VerticalAlignment="Center" Click="IpLookupButton_Click" /> <Button Content="Block IP" Width="120" Height="30" Margin="10,0" VerticalAlignment="Center" Click="BlockIpButton_Click" /> diff --git a/EonaCat.PortMonitor/MainWindow.xaml.cs b/EonaCat.PortMonitor/MainWindow.xaml.cs index 4e18374..712d362 100644 --- a/EonaCat.PortMonitor/MainWindow.xaml.cs +++ b/EonaCat.PortMonitor/MainWindow.xaml.cs @@ -15,8 +15,8 @@ using System.Net.Http; using System.Windows.Media; using Application = System.Windows.Application; using Brushes = System.Drawing.Brushes; -using Brush = System.Drawing.Brush; using System.Windows.Threading; +using Color = System.Drawing.Color; namespace EonaCat.PortMonitor { @@ -189,7 +189,7 @@ namespace EonaCat.PortMonitor System.Media.SystemSounds.Asterisk.Play(); var detailsWindow = new ConnectionDetailsWindow(conn); - detailsWindow.Show(); + detailsWindow.ShowDialog(); } private void DataGrid_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) @@ -235,103 +235,156 @@ namespace EonaCat.PortMonitor private async void MonitorConnections(object state) { - // Store the currently selected connection before the update - ConnectionInfo selectedConnection = null; - - // Store the selected item from the DataGrid - Dispatcher.Invoke(new Action(() => + try { - selectedConnection = NetworkDataGrid.SelectedItem as ConnectionInfo; - })); + ConnectionInfo selectedConnection = null; - var currentConnections = await Task.Run(() => GetActiveConnections()); - var inboundConnections = currentConnections.Where(c => IsInboundConnection(c)).ToList(); - var outboundConnections = currentConnections.Where(c => IsOutboundConnection(c)).ToList(); - int totalConnections = currentConnections.Count; - - // Compare and update connections with the existing ones - var newConnections = currentConnections.Where(c => !_previousConnections.Any(p => p.LocalAddress == c.LocalAddress && p.LocalPort == c.LocalPort)).ToList(); - var closedConnections = _previousConnections.Where(p => !currentConnections.Any(c => c.LocalAddress == p.LocalAddress && c.LocalPort == p.LocalPort)).ToList(); - var stateChangedConnections = currentConnections.Where(c => _previousConnections.Any(p => p.LocalAddress == c.LocalAddress && p.LocalPort == c.LocalPort && p.State != c.State)).ToList(); - - // Add new connections or update existing ones - foreach (var newConn in newConnections) - { - newConn.ConnectionStatus = "New"; - if (newConn.FirstConnectionTime == DateTime.MinValue) + // Store the currently selected connection + Dispatcher.Invoke(() => { - newConn.FirstConnectionTime = DateTime.Now; - } + selectedConnection = NetworkDataGrid.SelectedItem as ConnectionInfo; + }); - // Add the new connection to the collection - Dispatcher.Invoke(() => Connections.Add(newConn)); - await NotifyNewConnectionAsync(newConn); - } + var currentConnections = await Task.Run(GetActiveConnections); - // Handle closed connections - foreach (var closedConn in closedConnections) - { - var conn = Connections.FirstOrDefault(c => c.LocalAddress == closedConn.LocalAddress && c.LocalPort == closedConn.LocalPort); - if (conn != null) + var inboundConnections = currentConnections.Where(IsInboundConnection).ToList(); + var outboundConnections = currentConnections.Where(IsOutboundConnection).ToList(); + int totalConnections = currentConnections.Count; + + // Identify new connections + var newConnections = currentConnections + .Where(c => !_previousConnections.Any(p => p.LocalAddress == c.LocalAddress && p.LocalPort == c.LocalPort)) + .ToList(); + + // Identify closed connections + var closedConnections = _previousConnections + .Where(p => !currentConnections.Any(c => c.LocalAddress == p.LocalAddress && c.LocalPort == p.LocalPort)) + .ToList(); + + // Identify state-changed connections + var stateChangedConnections = currentConnections + .Where(c => _previousConnections.Any(p => + p.LocalAddress == c.LocalAddress && + p.LocalPort == c.LocalPort && + p.State != c.State)) + .ToList(); + + await Dispatcher.InvokeAsync(() => { - conn.ConnectionStatus = "Closed"; - - // Remove the connection if the status was set to closed for more than 5 seconds - if (conn.ConnectionDuration.TotalSeconds > 5) + foreach (var newConn in newConnections) { - await Dispatcher.InvokeAsync(() => Connections.Remove(conn)); + var existingConn = Connections.FirstOrDefault(c => c.LocalAddress == newConn.LocalAddress && c.LocalPort == newConn.LocalPort); + if (existingConn == null) + { + if (newConn.FirstConnectionTime == DateTime.MinValue) + newConn.FirstConnectionTime = DateTime.Now; + + newConn.ConnectionStatus = "New"; + newConn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.LightGreen)); // Softer green for new connections + Connections.Add(newConn); + } + else + { + existingConn.ConnectionStatus = "Updated"; + existingConn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.LightGreen)); // Softer green for updated connections + } } - } - } - // Handle state changes - foreach (var stateChangedConn in stateChangedConnections) - { - var conn = Connections.FirstOrDefault(c => c.LocalAddress == stateChangedConn.LocalAddress && c.LocalPort == stateChangedConn.LocalPort); - if (conn != null) - { - conn.ConnectionStatus = "State Changed"; - conn.BackgroundColor = Brushes.Yellow; - - var timer = new DispatcherTimer + foreach (var closedConn in closedConnections) { - Interval = TimeSpan.FromSeconds(1) - }; - timer.Tick += (sender, args) => + var conn = Connections.FirstOrDefault(c => c.LocalAddress == closedConn.LocalAddress && c.LocalPort == closedConn.LocalPort); + if (conn != null) + { + conn.ConnectionStatus = "Closed"; + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.Gray)); // Softer gray for closed connections + + Task.Delay(2000).ContinueWith(_ => + { + Dispatcher.Invoke(() => Connections.Remove(conn)); + }); + } + } + + foreach (var stateChangedConn in stateChangedConnections) { - conn.BackgroundColor = Brushes.Transparent; - timer.Stop(); - }; - timer.Start(); - } - } + var conn = Connections.FirstOrDefault(c => c.LocalAddress == stateChangedConn.LocalAddress && c.LocalPort == stateChangedConn.LocalPort); + if (conn != null) + { + conn.ConnectionStatus = "State Changed"; + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.Yellow)); // Softer yellow for state changes - await Dispatcher.InvokeAsync(() => - { - InboundDataGrid.ItemsSource = Connections.Where(x => IsInboundConnection(x)); - OutboundDataGrid.ItemsSource = Connections.Where(x => IsOutboundConnection(x)); + var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; + timer.Tick += (sender, args) => + { + conn.ConnectionColor = new SolidColorBrush(Colors.Transparent); + timer.Stop(); + }; + timer.Start(); + } + } - NetworkDataGrid.Items.Refresh(); - FilterConnections_KeyUp(null, null); - UpdateConnectionStats(totalConnections, inboundConnections.Count, outboundConnections.Count); - }); - - // Re-select the previously selected item after the refresh - if (selectedConnection != null) - { - var selectedItem = Connections.FirstOrDefault(c => c.LocalAddress == selectedConnection.LocalAddress && c.LocalPort == selectedConnection.LocalPort); - if (selectedItem != null) - { - Dispatcher.Invoke(() => + // Apply colors based on connection state with softer variants + foreach (var conn in Connections) { - // Set the previously selected item back to the DataGrid - NetworkDataGrid.SelectedItem = selectedItem; - }); - } - } + switch (conn.State) + { + case "IDLE": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.Red)); // Softer red + break; + case "LISTENING": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.Blue)); // Softer blue + break; + case "SYN_SENT": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.Orange)); // Softer orange + break; + case "SYN_RECEIVED": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.Purple)); // Softer purple + break; + case "ESTABLISHED": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.DarkGreen)); // Softer dark green + break; + case "CLOSE_WAIT": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.Brown)); // Softer brown + break; + case "TIME_WAIT": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.DarkGray)); // Softer dark gray + break; + case "FIN_WAIT_1": + case "FIN_WAIT_2": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.LightYellow)); // Softer light yellow + break; + case "LAST_ACK": + conn.ConnectionColor = new SolidColorBrush(AdjustColorBrightness(Colors.DarkOrange)); // Softer dark orange + break; + default: + conn.ConnectionColor = new SolidColorBrush(Colors.Transparent); // Default (no color) + break; + } + } - // Update the previousConnections list for the next iteration - _previousConnections = currentConnections; + // Update DataGrids + InboundDataGrid.ItemsSource = Connections.Where(IsInboundConnection).ToList(); + OutboundDataGrid.ItemsSource = Connections.Where(IsOutboundConnection).ToList(); + NetworkDataGrid.ItemsSource = Connections; + + FilterConnections_KeyUp(null, null); + UpdateConnectionStats(totalConnections, inboundConnections.Count, outboundConnections.Count); + }); + } + catch (Exception ex) + { + // Handle any exceptions appropriately + Console.WriteLine($"Error monitoring connections: {ex.Message}"); + } + } + + // Method to adjust the color brightness and make it softer + private System.Windows.Media.Color AdjustColorBrightness(System.Windows.Media.Color color) + { + byte r = (byte)(color.R + (255 - color.R) * 0.5); // Lighten the red component + byte g = (byte)(color.G + (255 - color.G) * 0.5); // Lighten the green component + byte b = (byte)(color.B + (255 - color.B) * 0.5); // Lighten the blue component + return System.Windows.Media.Color.FromArgb(180, r, g, b); // alpha = 180 for a softer color } private void UpdateConnectionStats(int total, int inbound, int outbound) @@ -465,9 +518,6 @@ namespace EonaCat.PortMonitor } } - - - private void FilterConnections_SelectionChanged(object sender, SelectionChangedEventArgs e) { FilterConnections_KeyUp(sender, null); @@ -610,59 +660,40 @@ namespace EonaCat.PortMonitor } // Retrieve current background color - SolidColorBrush currentBg = (SolidColorBrush)Application.Current.Resources["DynamicBackgroundColor"]; + System.Windows.Media.SolidColorBrush currentBg = (System.Windows.Media.SolidColorBrush)Application.Current.Resources["DynamicBackgroundColor"]; - if (currentBg.Color == Colors.Black) // Dark Mode → Light Mode + if (currentBg.Color == System.Windows.Media.Colors.Black) // Dark Mode → Light Mode { - Application.Current.Resources["DynamicBackgroundColor"] = new SolidColorBrush(Colors.White); - Application.Current.Resources["DynamicTextColor"] = new SolidColorBrush(Colors.Black); + Application.Current.Resources["DynamicBackgroundColor"] = new System.Windows.Media.SolidColorBrush(Colors.White); + Application.Current.Resources["DynamicTextColor"] = new System.Windows.Media.SolidColorBrush(Colors.Black); btnTheme.Content = "🌙"; // Set icon to moon for dark mode } else // Light Mode → Dark Mode { - Application.Current.Resources["DynamicBackgroundColor"] = new SolidColorBrush(Colors.Black); - Application.Current.Resources["DynamicTextColor"] = new SolidColorBrush(Colors.White); + Application.Current.Resources["DynamicBackgroundColor"] = new System.Windows.Media.SolidColorBrush(Colors.Black); + Application.Current.Resources["DynamicTextColor"] = new System.Windows.Media.SolidColorBrush(Colors.White); btnTheme.Content = "🌞"; // Set icon to sun for light mode } } - } - public class ConnectionInfo : INotifyPropertyChanged - { - private Brush _backgroundColor; - - public string Protocol { get; set; } - public string LocalAddress { get; set; } - public int LocalPort { get; set; } - public string RemoteAddress { get; set; } - public int RemotePort { get; set; } - public string State { get; set; } - public int ProcessId { get; set; } - public string ProcessName { get; set; } - public DateTime ConnectionTime { get; set; } - public DateTime FirstConnectionTime { get; set; } - public string ConnectionStatus { get; set; } - public TimeSpan ConnectionDuration => DateTime.Now - FirstConnectionTime; - public string FormattedConnectionDuration => ConnectionDuration.ToString(@"hh\:mm\:ss"); - - public Brush BackgroundColor + private void ProcessPathButton_Click(object sender, RoutedEventArgs e) { - get { return _backgroundColor; } - set + // Check if an item is selected in the DataGrid + if (NetworkDataGrid.SelectedItem is ConnectionInfo selectedConnection) { - if (_backgroundColor != value) + try { - _backgroundColor = value; - OnPropertyChanged(nameof(BackgroundColor)); + var process = Process.GetProcessById(selectedConnection.ProcessId); + if (process != null && process.MainModule != null) + { + Process.Start("explorer.exe", $"/select, \"{process.MainModule.FileName}\""); + } + } + catch (Exception ex) + { + MessageBox.Show($"Failed to get process path: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } } - - public event PropertyChangedEventHandler PropertyChanged; - - protected virtual void OnPropertyChanged(string propertyName) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } } }