700 lines
30 KiB
C#
700 lines
30 KiB
C#
using EonaCat.Json;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Xml.Serialization;
|
|
using System.Collections.ObjectModel;
|
|
using System.Text.RegularExpressions;
|
|
using System.ComponentModel;
|
|
using System.Windows.Input;
|
|
using EonaCat.Helpers.Commands;
|
|
using System.Text;
|
|
using MessageBox = System.Windows.MessageBox;
|
|
using System.Net.Http;
|
|
using System.Windows.Media;
|
|
using Application = System.Windows.Application;
|
|
using Brushes = System.Drawing.Brushes;
|
|
using System.Windows.Threading;
|
|
using Color = System.Drawing.Color;
|
|
|
|
namespace EonaCat.PortMonitor
|
|
{
|
|
public partial class MainWindow : Window
|
|
{
|
|
public ObservableCollection<ConnectionInfo> Connections { get; set; } = new ObservableCollection<ConnectionInfo>();
|
|
private List<ConnectionInfo> _previousConnections = new List<ConnectionInfo>();
|
|
private BackgroundWorker _monitorWorker;
|
|
private int _interval = 1 * 1000;
|
|
WPF.Tray.TrayIcon _trayIcon = new WPF.Tray.TrayIcon();
|
|
|
|
public bool MinimizeToTray { get; private set; }
|
|
public bool MinimizeOnStartup { get; private set; }
|
|
public bool ShowPopups { get; private set; } = true;
|
|
public bool FirstRun { get; private set; } = true;
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
DataContext = this;
|
|
|
|
NetworkDataGrid.Items.Clear();
|
|
NetworkDataGrid.ItemsSource = Connections;
|
|
|
|
this.StateChanged += MainWindow_StateChanged;
|
|
|
|
SetupTrayIcon();
|
|
|
|
LoadSettings();
|
|
|
|
_monitorWorker = new BackgroundWorker();
|
|
_monitorWorker.DoWork += MonitorWorker_DoWork;
|
|
_monitorWorker.RunWorkerAsync();
|
|
}
|
|
|
|
protected override void OnActivated(EventArgs e)
|
|
{
|
|
base.OnActivated(e);
|
|
if (FirstRun)
|
|
{
|
|
if (MinimizeToTray || MinimizeOnStartup)
|
|
{
|
|
// Minimize to tray on first run
|
|
Hide();
|
|
FirstRun = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LoadSettings()
|
|
{
|
|
if (File.Exists("settings.json"))
|
|
{
|
|
var json = File.ReadAllText("settings.json");
|
|
var settings = JsonHelper.ToObject<dynamic>(json);
|
|
if (settings != null)
|
|
{
|
|
if (settings.MinimizeToTray != null)
|
|
{
|
|
MinimizeToTray = (bool)settings.MinimizeToTray;
|
|
}
|
|
|
|
if (settings.MinimizeOnStartup != null)
|
|
{
|
|
MinimizeOnStartup = (bool)settings.MinimizeOnStartup;
|
|
chkMinimize.IsChecked = MinimizeOnStartup;
|
|
}
|
|
|
|
if (settings.ShowPopups != null)
|
|
{
|
|
ShowPopups = (bool)settings.ShowPopups;
|
|
chkShowPopups.IsChecked = ShowPopups;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void MainWindow_StateChanged(object? sender, EventArgs e)
|
|
{
|
|
if (WindowState == WindowState.Minimized)
|
|
{
|
|
// Minimize to tray and hide the window
|
|
this.Hide();
|
|
}
|
|
}
|
|
|
|
private void SetupTrayIcon()
|
|
{
|
|
// Load the icon from embedded resource
|
|
var icon = System.Drawing.Icon.ExtractAssociatedIcon(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
|
_trayIcon.Icon = icon;
|
|
_trayIcon.TrayLeftMouseUp += (sender, args) =>
|
|
{
|
|
// Show the main window when the tray icon is clicked
|
|
WindowState = WindowState.Normal;
|
|
Show();
|
|
Activate();
|
|
};
|
|
|
|
_trayIcon.TrayRightMouseUp += (sender, args) =>
|
|
{
|
|
// Generate a context menu for the tray icon
|
|
var contextMenu = new System.Windows.Controls.ContextMenu();
|
|
contextMenu.Items.Add(new MenuItem { Header = "Show", Command = new GiveCommand(() => { Show(); WindowState = WindowState.Normal; }) });
|
|
contextMenu.Items.Add(new MenuItem
|
|
{
|
|
Header = "Exit",
|
|
Command = new GiveCommand(() =>
|
|
{
|
|
Close();
|
|
})
|
|
});
|
|
_trayIcon.ContextMenu = contextMenu;
|
|
};
|
|
}
|
|
|
|
protected override void OnClosing(CancelEventArgs e)
|
|
{
|
|
// Save settings before closing
|
|
var settings = new
|
|
{
|
|
MinimizeToTray = this.WindowState == WindowState.Minimized,
|
|
MinimizeOnStartup = chkMinimize.IsChecked == true,
|
|
ShowPopups = chkShowPopups.IsChecked == true
|
|
};
|
|
File.WriteAllBytes("settings.json", Encoding.UTF8.GetBytes(JsonHelper.ToJson(settings)));
|
|
|
|
base.OnClosing(e);
|
|
}
|
|
|
|
private void MonitorWorker_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
while (true)
|
|
{
|
|
MonitorConnections(null);
|
|
Thread.Sleep(_interval);
|
|
}
|
|
}
|
|
|
|
private async Task NotifyNewConnectionAsync(ConnectionInfo conn)
|
|
{
|
|
if (!ShowPopups)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Create a new notification manager
|
|
var notificationManager = new WPF.Popup.NotificationManager();
|
|
|
|
// Set up the popup's title and content
|
|
string popupTitle = $"New Connection: {conn.Protocol} {conn.LocalAddress}:{conn.LocalPort} -> {conn.RemoteAddress}:{conn.RemotePort}";
|
|
string popupContent = $"Process: {conn.ProcessName}\nState: {conn.State}";
|
|
|
|
// Set up the popup
|
|
var notification = new WPF.Popup.NotificationContent
|
|
{
|
|
Title = popupTitle,
|
|
Message = popupContent,
|
|
Type = WPF.Popup.NotificationType.Information,
|
|
};
|
|
|
|
// Show the popup
|
|
await notificationManager.ShowAsync(notification, expirationTime: TimeSpan.FromSeconds(3), onClick: new Action(() => { ShowConnectionDetails(conn); }));
|
|
}
|
|
|
|
|
|
private void ShowConnectionDetails(ConnectionInfo conn)
|
|
{
|
|
// Play a sound when the notification is clicked
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
|
|
var detailsWindow = new ConnectionDetailsWindow(conn);
|
|
detailsWindow.ShowDialog();
|
|
}
|
|
|
|
private void DataGrid_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
|
|
{
|
|
// Get the DataGrid that triggered the event
|
|
DataGrid dataGrid = sender as DataGrid;
|
|
|
|
if (dataGrid.SelectedItem != null)
|
|
{
|
|
ShowConnectionDetails(dataGrid.SelectedItem as ConnectionInfo);
|
|
}
|
|
}
|
|
|
|
private List<ConnectionInfo> GetActiveConnections()
|
|
{
|
|
var connectionList = new List<ConnectionInfo>();
|
|
foreach (var conn in RunNetstatCommand())
|
|
{
|
|
if (string.IsNullOrEmpty(conn)) continue;
|
|
|
|
var match = ParseNetstatLine(conn);
|
|
if (match.Success)
|
|
{
|
|
var connInfo = new ConnectionInfo
|
|
{
|
|
Protocol = match.Groups["protocol"].Value,
|
|
LocalAddress = match.Groups["localAddress"].Value,
|
|
LocalPort = int.Parse(match.Groups["localPort"].Value),
|
|
RemoteAddress = match.Groups["remoteAddress"].Value,
|
|
RemotePort = int.Parse(match.Groups["remotePort"].Value),
|
|
State = string.IsNullOrEmpty(match.Groups["state"].Value) ? string.Empty : match.Groups["state"].Value, // Handle missing state for UDP
|
|
ProcessId = string.IsNullOrEmpty(match.Groups["pid"].Value) ? 0 : int.Parse(match.Groups["pid"].Value), // Default PID to 0 if missing
|
|
ProcessName = string.IsNullOrEmpty(match.Groups["pid"].Value) ? string.Empty : GetProcessName(int.Parse(match.Groups["pid"].Value)),
|
|
ConnectionTime = DateTime.Now,
|
|
ConnectionStatus = string.Empty
|
|
};
|
|
|
|
connectionList.Add(connInfo);
|
|
}
|
|
}
|
|
return connectionList;
|
|
}
|
|
|
|
private async void MonitorConnections(object state)
|
|
{
|
|
try
|
|
{
|
|
ConnectionInfo selectedConnection = null;
|
|
|
|
// Store the currently selected connection
|
|
Dispatcher.Invoke(() =>
|
|
{
|
|
selectedConnection = NetworkDataGrid.SelectedItem as ConnectionInfo;
|
|
});
|
|
|
|
var currentConnections = await Task.Run(GetActiveConnections);
|
|
|
|
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(() =>
|
|
{
|
|
foreach (var newConn in newConnections)
|
|
{
|
|
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
|
|
}
|
|
}
|
|
|
|
foreach (var closedConn in closedConnections)
|
|
{
|
|
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)
|
|
{
|
|
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
|
|
|
|
var timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
|
|
timer.Tick += (sender, args) =>
|
|
{
|
|
conn.ConnectionColor = new SolidColorBrush(Colors.Transparent);
|
|
timer.Stop();
|
|
};
|
|
timer.Start();
|
|
}
|
|
}
|
|
|
|
// Apply colors based on connection state with softer variants
|
|
foreach (var conn in Connections)
|
|
{
|
|
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 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)
|
|
{
|
|
var tcpConnections = Connections.Count(c => c.Protocol == "TCP");
|
|
var udpConnections = Connections.Count(c => c.Protocol == "UDP");
|
|
|
|
var avgConnectionTime = Connections.Average(c => (DateTime.Now - c.ConnectionTime).TotalSeconds);
|
|
TcpUdpStatsText.Text = $"TCP Connections: {tcpConnections}\nUDP Connections: {udpConnections}\nAverage Connection Time: {avgConnectionTime:F2} seconds\nTotal: {total}\nInbound: {inbound}\nOutbound: {outbound}";
|
|
}
|
|
|
|
private bool IsInboundConnection(ConnectionInfo connection)
|
|
{
|
|
// Inbound: LocalAddress is valid, and the machine is accepting the connection (server-side).
|
|
return IsValidIpAddress(connection.LocalAddress) &&
|
|
connection.LocalAddress != "0.0.0.0" &&
|
|
connection.LocalAddress != "::" &&
|
|
!string.IsNullOrEmpty(connection.RemoteAddress) &&
|
|
connection.RemoteAddress != "0.0.0.0" &&
|
|
connection.RemoteAddress != "::" &&
|
|
connection.RemoteAddress != "N/A" &&
|
|
connection.RemotePort != 0;
|
|
}
|
|
|
|
private bool IsOutboundConnection(ConnectionInfo connection)
|
|
{
|
|
// Outbound: LocalAddress is valid, and the machine is initiating the connection (client-side).
|
|
return IsValidIpAddress(connection.LocalAddress) &&
|
|
connection.LocalAddress != "0.0.0.0" &&
|
|
connection.LocalAddress != "::" &&
|
|
IsValidIpAddress(connection.RemoteAddress) &&
|
|
connection.RemoteAddress != "0.0.0.0" &&
|
|
connection.RemoteAddress != "::" &&
|
|
connection.RemoteAddress != "N/A" &&
|
|
connection.LocalPort != 0;
|
|
}
|
|
|
|
private bool IsValidIpAddress(string ipAddress)
|
|
{
|
|
return !string.IsNullOrEmpty(ipAddress) && (IsValidIPv4(ipAddress) || IsValidIPv6(ipAddress));
|
|
}
|
|
|
|
private bool IsValidIPv4(string ipAddress)
|
|
{
|
|
return System.Net.IPAddress.TryParse(ipAddress, out var ip) && ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork;
|
|
}
|
|
|
|
private bool IsValidIPv6(string ipAddress)
|
|
{
|
|
return System.Net.IPAddress.TryParse(ipAddress, out var ip) && ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6;
|
|
}
|
|
|
|
private List<string> RunNetstatCommand()
|
|
{
|
|
var result = new List<string>();
|
|
try
|
|
{
|
|
ProcessStartInfo startInfo = new ProcessStartInfo("netstat", "-ano")
|
|
{
|
|
RedirectStandardOutput = true,
|
|
UseShellExecute = false,
|
|
CreateNoWindow = true
|
|
};
|
|
|
|
using (Process process = Process.Start(startInfo))
|
|
{
|
|
using (var reader = process.StandardOutput)
|
|
{
|
|
string line;
|
|
while ((line = reader.ReadLine()) != null)
|
|
{
|
|
result.Add(line);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Error running netstat: {ex.Message}");
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private Match ParseNetstatLine(string line)
|
|
{
|
|
// Regular expression for both TCP and UDP connections, IPv4 and IPv6.
|
|
var regex = new Regex(@"(?<protocol>TCP|UDP)\s+(?<localAddress>[\d\.]+|\[?[A-F0-9:]+\]?):(?<localPort>\d+)\s+(?<remoteAddress>[\d\.]+|\[?[A-F0-9:]+\]?):(?<remotePort>\d+)\s*(?<state>\S*)?\s*(?<pid>\d+)?");
|
|
var match = regex.Match(line);
|
|
return match;
|
|
}
|
|
|
|
private string GetProcessName(int pid)
|
|
{
|
|
try
|
|
{
|
|
var process = Process.GetProcessById(pid);
|
|
return process.ProcessName;
|
|
}
|
|
catch
|
|
{
|
|
return "N/A";
|
|
}
|
|
}
|
|
|
|
private void FilterConnections_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
|
|
{
|
|
// Get the filter keyword from the input box
|
|
var keywordFilter = KeywordFilter.Text.ToLower();
|
|
|
|
// Filter the connections based on the keyword
|
|
var filteredConnections = Connections?.Where(c =>
|
|
(string.IsNullOrEmpty(keywordFilter) ||
|
|
c.ProcessName.ToLower().Contains(keywordFilter) ||
|
|
c.RemoteAddress.ToLower().Contains(keywordFilter) ||
|
|
c.LocalAddress.ToLower().Contains(keywordFilter) ||
|
|
c.State.ToLower().Contains(keywordFilter) ||
|
|
c.Protocol.ToLower().Contains(keywordFilter) ||
|
|
c.LocalPort.ToString().Contains(keywordFilter) ||
|
|
c.RemotePort.ToString().Contains(keywordFilter)
|
|
)
|
|
).ToList();
|
|
|
|
// Clear the existing items and add filtered ones to the ObservableCollection
|
|
Connections.Clear();
|
|
if (filteredConnections != null)
|
|
{
|
|
foreach (var conn in filteredConnections)
|
|
{
|
|
Connections.Add(conn);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void FilterConnections_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
|
{
|
|
FilterConnections_KeyUp(sender, null);
|
|
}
|
|
|
|
private void ExportToJsonButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var json = JsonHelper.ToJson(Connections, Json.Formatting.Indented);
|
|
File.WriteAllText("connections.json", json);
|
|
MessageBox.Show("Connections exported to connections.json", "Export Successful", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
|
|
private void ExportToXmlButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var xmlSerializer = new XmlSerializer(typeof(List<ConnectionInfo>));
|
|
using (var writer = new StreamWriter("connections.xml"))
|
|
{
|
|
xmlSerializer.Serialize(writer, Connections);
|
|
}
|
|
MessageBox.Show("Connections exported to connections.xml", "Export Successful", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
|
|
private void ExportToCsvButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var csvLines = new List<string> { "Protocol,LocalAddress,LocalPort,RemoteAddress,RemotePort,State,ProcessName,ConnectionTime" };
|
|
csvLines.AddRange(Connections.Select(c => $"{c.Protocol},{c.LocalAddress},{c.LocalPort},{c.RemoteAddress},{c.RemotePort},{c.State},{c.ProcessName},{c.ConnectionTime}"));
|
|
|
|
File.WriteAllLines("connections.csv", csvLines);
|
|
MessageBox.Show("Connections exported to connections.csv", "Export Successful", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
|
|
private void SaveFilterPresetButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var filters = new
|
|
{
|
|
Keywords = KeywordFilter.Text,
|
|
};
|
|
|
|
var json = JsonHelper.ToJson(filters);
|
|
File.WriteAllText("filterPreset.json", json);
|
|
}
|
|
|
|
private void LoadFilterPresetButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (File.Exists("filterPreset.json"))
|
|
{
|
|
var json = File.ReadAllText("filterPreset.json");
|
|
var filters = JsonHelper.ToObject<dynamic>(json);
|
|
|
|
KeywordFilter.Text = filters.Keywords;
|
|
|
|
FilterConnections_KeyUp(null, null);
|
|
}
|
|
}
|
|
|
|
private void ExportToHtmlButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
var htmlContent = "<html><body><table border='1'><tr><th>Protocol</th><th>LocalAddress</th><th>LocalPort</th><th>RemoteAddress</th><th>RemotePort</th><th>State</th><th>ProcessName</th><th>ConnectionTime</th></tr>";
|
|
foreach (var conn in Connections)
|
|
{
|
|
htmlContent += $"<tr><td>{conn.Protocol}</td><td>{conn.LocalAddress}</td><td>{conn.LocalPort}</td><td>{conn.RemoteAddress}</td><td>{conn.RemotePort}</td><td>{conn.State}</td><td>{conn.ProcessName}</td><td>{conn.ConnectionTime}</td></tr>";
|
|
}
|
|
htmlContent += "</table></body></html>";
|
|
|
|
File.WriteAllText("connections.html", htmlContent);
|
|
MessageBox.Show("Connections exported to connections.html", "Export Successful", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
|
|
private void chkMinimize_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
MinimizeOnStartup = chkMinimize.IsChecked == true;
|
|
}
|
|
|
|
private void chkShowPopups_Checked(object sender, RoutedEventArgs e)
|
|
{
|
|
ShowPopups = chkShowPopups.IsChecked == true;
|
|
}
|
|
|
|
private void KillProcessButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (NetworkDataGrid.SelectedItem is ConnectionInfo selectedConnection)
|
|
{
|
|
try
|
|
{
|
|
var process = Process.GetProcessById(selectedConnection.ProcessId);
|
|
process.Kill();
|
|
MessageBox.Show($"Process {selectedConnection.ProcessName} (PID: {selectedConnection.ProcessId}) terminated.", "Process Killed", MessageBoxButton.OK, MessageBoxImage.Warning);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageBox.Show($"Failed to terminate process: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private async void IpLookupButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
if (NetworkDataGrid.SelectedItem is ConnectionInfo selectedConnection)
|
|
{
|
|
string apiUrl = $"https://reallyfreegeoip.org/json/{selectedConnection.RemoteAddress}";
|
|
using (HttpClient client = new HttpClient())
|
|
{
|
|
var response = await client.GetStringAsync(apiUrl);
|
|
MessageBox.Show(response, "IP Lookup", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void BlockIpButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
// Check if an item is selected in the DataGrid
|
|
if (NetworkDataGrid.SelectedItem is ConnectionInfo selectedConnection)
|
|
{
|
|
// Ask the user for confirmation
|
|
var result = MessageBox.Show(
|
|
$"Are you sure you want to block the IP address: {selectedConnection.RemoteAddress}?",
|
|
"Confirm Block",
|
|
MessageBoxButton.YesNo,
|
|
MessageBoxImage.Question
|
|
);
|
|
|
|
// If the user clicks 'Yes', proceed with blocking the IP
|
|
if (result == MessageBoxResult.Yes)
|
|
{
|
|
string command = $"netsh advfirewall firewall add rule name=\"Blocked {selectedConnection.RemoteAddress}\" dir=in action=block remoteip={selectedConnection.RemoteAddress}";
|
|
Process.Start(new ProcessStartInfo("cmd.exe", "/C " + command) { CreateNoWindow = true });
|
|
MessageBox.Show($"Blocked IP: {selectedConnection.RemoteAddress}", "Firewall Rule Added", MessageBoxButton.OK, MessageBoxImage.Information);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void btnTheme_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
// Ensure the resources exist
|
|
if (!Application.Current.Resources.Contains("DynamicBackgroundColor") ||
|
|
!Application.Current.Resources.Contains("DynamicTextColor"))
|
|
{
|
|
MessageBox.Show("Theme resources are missing!", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
|
|
return;
|
|
}
|
|
|
|
// Retrieve current background color
|
|
System.Windows.Media.SolidColorBrush currentBg = (System.Windows.Media.SolidColorBrush)Application.Current.Resources["DynamicBackgroundColor"];
|
|
|
|
if (currentBg.Color == System.Windows.Media.Colors.Black) // Dark Mode → Light Mode
|
|
{
|
|
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 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
|
|
}
|
|
}
|
|
|
|
private void ProcessPathButton_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
// Check if an item is selected in the DataGrid
|
|
if (NetworkDataGrid.SelectedItem is ConnectionInfo selectedConnection)
|
|
{
|
|
try
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|