using System.ComponentModel; using System.Diagnostics; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Security.Cryptography; using MaxMind.GeoIP2; using Microsoft.Win32.TaskScheduler; using Task = System.Threading.Tasks.Task; namespace Netch.Utils; public static class Utils { public static void Open(string path) { try { Process.Start(new ProcessStartInfo { FileName = "explorer.exe", Arguments = path, UseShellExecute = true }); } catch (Exception e) { Log.Warning(e, "Open \"{Uri}\" failed", path); } } public static async Task TCPingAsync(IPAddress ip, int port, int timeout = 1000, CancellationToken ct = default) { using var client = new TcpClient(ip.AddressFamily); var stopwatch = Stopwatch.StartNew(); var task = client.ConnectAsync(ip, port); var resTask = await Task.WhenAny(task, Task.Delay(timeout, ct)); stopwatch.Stop(); if (resTask == task && client.Connected) { var t = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds); return t; } return timeout; } public static async Task ICMPingAsync(IPAddress ip, int timeout = 1000) { var reply = await new Ping().SendPingAsync(ip, timeout); if (reply.Status == IPStatus.Success) return Convert.ToInt32(reply.RoundtripTime); return timeout; } public static async Task GetCityCodeAsync(string address) { var i = address.IndexOf(':'); if (i != -1) address = address[..i]; string? country = null; try { var databaseReader = new DatabaseReader("bin\\GeoLite2-Country.mmdb"); if (IPAddress.TryParse(address, out _)) { country = databaseReader.Country(address).Country.IsoCode; } else { var dnsResult = await DnsUtils.LookupAsync(address); if (dnsResult != null) country = databaseReader.Country(dnsResult).Country.IsoCode; } } catch { // ignored } country ??= "Unknown"; return country; } public static async Task Sha256CheckSumAsync(string filePath) { if (!File.Exists(filePath)) return ""; try { await using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true); return await Sha256ComputeCoreAsync(fileStream); } catch (Exception e) { Log.Warning(e, $"Compute file \"{filePath}\" sha256 failed"); return ""; } } private static async Task Sha256ComputeCoreAsync(Stream stream) { using var sha256 = SHA256.Create(); var hash = await sha256.ComputeHashAsync(stream); return string.Concat(hash.Select(b => b.ToString("x2"))); } public static string GetFileVersion(string file) { if (File.Exists(file)) return FileVersionInfo.GetVersionInfo(file).FileVersion ?? ""; return ""; } public static void DrawCenterComboBox(object sender, DrawItemEventArgs e) { if (sender is ComboBox cbx) { e.DrawBackground(); if (e.Index < 0) return; TextRenderer.DrawText(e.Graphics, cbx.Items[e.Index].ToString(), cbx.Font, e.Bounds, (e.State & DrawItemState.Selected) == DrawItemState.Selected ? SystemColors.HighlightText : cbx.ForeColor, TextFormatFlags.HorizontalCenter); } } public static void ComponentIterator(in Component component, in Action func) { func.Invoke(component); switch (component) { case ListView listView: // ListView sub item foreach (var item in listView.Columns.Cast()) ComponentIterator(item, func); break; case ToolStripMenuItem toolStripMenuItem: // Iterator Menu strip sub item foreach (var item in toolStripMenuItem.DropDownItems.Cast()) ComponentIterator(item, func); break; case MenuStrip menuStrip: // Menu Strip foreach (var item in menuStrip.Items.Cast()) ComponentIterator(item, func); break; case ContextMenuStrip contextMenuStrip: foreach (var item in contextMenuStrip.Items.Cast()) ComponentIterator(item, func); break; case Control control: foreach (var c in control.Controls.Cast()) ComponentIterator(c, func); if (control.ContextMenuStrip != null) ComponentIterator(control.ContextMenuStrip, func); break; } } public static void RegisterNetchStartupItem() { const string TaskName = "Netch Startup"; var folder = TaskService.Instance.GetFolder("\\"); var taskIsExists = folder.Tasks.Any(task => task.Name == TaskName); if (Global.Settings.RunAtStartup) { if (taskIsExists) folder.DeleteTask(TaskName, false); var td = TaskService.Instance.NewTask(); td.RegistrationInfo.Author = "Netch"; td.RegistrationInfo.Description = "Netch run at startup."; td.Principal.RunLevel = TaskRunLevel.Highest; td.Triggers.Add(new LogonTrigger()); td.Actions.Add(new ExecAction(Global.NetchExecutable)); td.Settings.ExecutionTimeLimit = TimeSpan.Zero; td.Settings.DisallowStartIfOnBatteries = false; td.Settings.StopIfGoingOnBatteries = false; td.Settings.IdleSettings.StopOnIdleEnd = false; td.Settings.IdleSettings.RestartOnIdle = false; td.Settings.RunOnlyIfIdle = false; td.Settings.Compatibility = TaskCompatibility.V2_1; TaskService.Instance.RootFolder.RegisterTaskDefinition("Netch Startup", td); } else { if (taskIsExists) folder.DeleteTask(TaskName, false); } } public static void ChangeControlForeColor(Component component, Color color) { switch (component) { case TextBox _: case ComboBox _: if (((Control)component).ForeColor != color) ((Control)component).ForeColor = color; break; } } public static int SubnetToCidr(string value) { var subnet = IPAddress.Parse(value); return SubnetToCidr(subnet); } public static int SubnetToCidr(IPAddress subnet) { return subnet.GetAddressBytes().Sum(b => Convert.ToString(b, 2).Count(c => c == '1')); } public static string GetHostFromUri(string str) { var startIndex = str.LastIndexOf('/'); if (startIndex != -1) str = str[(startIndex + 1)..]; var endIndex = str.IndexOf(':'); return endIndex == -1 ? str : str[..endIndex]; } public static void ActivateVisibleWindows() { var forms = Application.OpenForms.Cast
().Where(f => f.Visible).ToList(); if (!forms.Any()) { Global.MainForm.Show(); Global.MainForm.WindowState = FormWindowState.Normal; Global.MainForm.Activate(); } else { foreach (var f in forms) { f.WindowState = FormWindowState.Normal; f.Activate(); } } } }