Files
Archive/netch/Netch/Utils/Utils.cs
2024-03-05 02:32:38 -08:00

273 lines
8.0 KiB
C#

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<int> 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<int> 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<string> 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<string> 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<string> 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<Component> func)
{
func.Invoke(component);
switch (component)
{
case ListView listView:
// ListView sub item
foreach (var item in listView.Columns.Cast<ColumnHeader>())
ComponentIterator(item, func);
break;
case ToolStripMenuItem toolStripMenuItem:
// Iterator Menu strip sub item
foreach (var item in toolStripMenuItem.DropDownItems.Cast<ToolStripItem>())
ComponentIterator(item, func);
break;
case MenuStrip menuStrip:
// Menu Strip
foreach (var item in menuStrip.Items.Cast<ToolStripItem>())
ComponentIterator(item, func);
break;
case ContextMenuStrip contextMenuStrip:
foreach (var item in contextMenuStrip.Items.Cast<ToolStripItem>())
ComponentIterator(item, func);
break;
case Control control:
foreach (var c in control.Controls.Cast<Control>())
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<Form>().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();
}
}
}
}