424 lines
15 KiB
C#
424 lines
15 KiB
C#
using Microsoft.VisualBasic;
|
||
using NPOI.SS.UserModel;
|
||
using NPOI.XSSF.UserModel;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Net;
|
||
using System.Net.Sockets;
|
||
using System.Security.Cryptography;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Windows.Controls;
|
||
using System.Windows.Media;
|
||
using System.Windows.Media.Imaging;
|
||
using System.Windows.Threading;
|
||
|
||
namespace Ramitta.lib
|
||
{
|
||
public static class Basic
|
||
{
|
||
#region 全局颜色
|
||
public static SolidColorBrush 经典紫色 = new SolidColorBrush(Color.FromRgb(92, 40, 147));
|
||
public static SolidColorBrush 错误红色 = new SolidColorBrush(Color.FromRgb(134, 27, 45));
|
||
public static SolidColorBrush 警告橙色 = new SolidColorBrush(Color.FromRgb(202, 81, 0));
|
||
public static SolidColorBrush 正常绿色 = new SolidColorBrush(Color.FromRgb(66, 164, 60));
|
||
public static SolidColorBrush 通知蓝色 = new SolidColorBrush(Color.FromRgb(0, 122, 204));
|
||
public static SolidColorBrush 背景黑色 = new SolidColorBrush(Color.FromRgb(30, 30, 30));
|
||
public static SolidColorBrush 默认灰色 = new SolidColorBrush(Color.FromRgb(66, 66, 66));
|
||
#endregion
|
||
|
||
#region 调试函数
|
||
public static void DebugBar(Label obj, String? text, SolidColorBrush? color=null)
|
||
{
|
||
if (obj == null) return;
|
||
// 通过Dispatcher确保在UI线程执行
|
||
obj.Dispatcher.Invoke(() =>
|
||
{
|
||
if (text!=null)obj.Content = text;
|
||
if (color != null) obj.Background = color;
|
||
|
||
|
||
// 强制刷新UI
|
||
obj.InvalidateVisual();
|
||
obj.InvalidateArrange();
|
||
obj.InvalidateMeasure();
|
||
obj.UpdateLayout();
|
||
// 处理Dispatcher队列中的其他挂起的操作,确保UI更新
|
||
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));
|
||
});
|
||
}
|
||
public static SolidColorBrush GenerateRandomColor(SolidColorBrush color = null, bool? requireLightColor = null)
|
||
{
|
||
// 如果 color 参数为 null,生成一个新的随机颜色
|
||
if (color == null)
|
||
{
|
||
Random random = new Random();
|
||
|
||
// 根据需求生成亮色或暗色
|
||
if (requireLightColor.HasValue)
|
||
{
|
||
int attempts = 0;
|
||
const int maxAttempts = 100; // 防止无限循环
|
||
|
||
while (attempts < maxAttempts)
|
||
{
|
||
byte r = (byte)random.Next(0, 256);
|
||
byte g = (byte)random.Next(0, 256);
|
||
byte b = (byte)random.Next(0, 256);
|
||
|
||
// 计算亮度 (使用常见的亮度公式)
|
||
double brightness = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
||
|
||
// 检查是否符合要求
|
||
bool isLight = brightness > 0.5;
|
||
|
||
if ((requireLightColor.Value && isLight) || (!requireLightColor.Value && !isLight))
|
||
{
|
||
color = new SolidColorBrush(Color.FromRgb(r, g, b));
|
||
break;
|
||
}
|
||
|
||
attempts++;
|
||
}
|
||
|
||
// 如果多次尝试仍未找到合适的颜色,使用默认方法
|
||
if (color == null)
|
||
{
|
||
byte r = (byte)random.Next(0, 256);
|
||
byte g = (byte)random.Next(0, 256);
|
||
byte b = (byte)random.Next(0, 256);
|
||
color = new SolidColorBrush(Color.FromRgb(r, g, b));
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 不限制亮度,使用原来的随机方法
|
||
byte r = (byte)random.Next(0, 256);
|
||
byte g = (byte)random.Next(0, 256);
|
||
byte b = (byte)random.Next(0, 256);
|
||
color = new SolidColorBrush(Color.FromRgb(r, g, b));
|
||
}
|
||
}
|
||
|
||
return color;
|
||
}
|
||
|
||
// 定义自定义异常类
|
||
public class DebugbarException : Exception
|
||
{
|
||
public string Message { get; }
|
||
public SolidColorBrush Brush { get; }
|
||
|
||
public DebugbarException(string message, SolidColorBrush brush)
|
||
: base(message)
|
||
{
|
||
Message = message;
|
||
Brush = brush;
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
#region 参数解析
|
||
public static Dictionary<string, string>? Startupe;
|
||
public static Dictionary<string, string> ParseCommandLineArgs(string[] args)
|
||
{
|
||
var arguments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
for (int i = 0; i < args.Length; i++)
|
||
{
|
||
string arg = args[i];
|
||
|
||
// 检查是否是参数名(以-或/开头)
|
||
if (arg.StartsWith("-") || arg.StartsWith("/"))
|
||
{
|
||
string key = arg.TrimStart('-', '/');
|
||
string value = "true"; // 默认值为true,表示开关存在
|
||
|
||
// 检查下一个参数是否是值(不以-或/开头)
|
||
if (i + 1 < args.Length && !args[i + 1].StartsWith("-") && !args[i + 1].StartsWith("/"))
|
||
{
|
||
value = args[i + 1];
|
||
i++; // 跳过下一个参数,因为已经被用作值
|
||
}
|
||
|
||
arguments[key] = value;
|
||
}
|
||
}
|
||
|
||
return arguments;
|
||
}
|
||
#endregion
|
||
|
||
#region 文件解析
|
||
public static bool IsPathExist(string databasePath)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(databasePath))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
return Directory.Exists(databasePath);
|
||
}
|
||
public static void FileWrite(string outputPath, string outputText, bool createDirectories = true,bool fileAdd = false)
|
||
{
|
||
string directory = Path.GetDirectoryName(outputPath);
|
||
if (createDirectories && !Directory.Exists(directory))
|
||
{
|
||
Directory.CreateDirectory(directory);
|
||
}
|
||
|
||
// 使用 StreamWriter 写入文件
|
||
using (StreamWriter writer = new StreamWriter(outputPath, false))
|
||
{
|
||
Debug.WriteLine(outputText);
|
||
writer.WriteLine(outputText);
|
||
}
|
||
}
|
||
public static string FileRead(string outputPath)
|
||
{
|
||
try
|
||
{
|
||
return File.ReadAllText(outputPath);
|
||
}
|
||
catch
|
||
{
|
||
throw;
|
||
}
|
||
}
|
||
|
||
// 获取路径下所有文件和文件夹,支持传入判断文件的函数
|
||
public static List<string> GetFilesAndDirectories(string path, bool? isDirectory = null, Func<string, bool> fileFilter = null, Func<string, string> outputFormat = null)
|
||
{
|
||
List<string> result = new List<string>();
|
||
|
||
// 获取文件夹
|
||
var directories = Directory.GetDirectories(path);
|
||
foreach (var dir in directories)
|
||
{
|
||
if (isDirectory == null || isDirectory == true)
|
||
{
|
||
// 如果指定了输出格式函数,则使用格式化函数;否则使用原始路径
|
||
result.Add(outputFormat == null ? dir : outputFormat(dir));
|
||
}
|
||
}
|
||
|
||
// 获取文件
|
||
var files = Directory.GetFiles(path);
|
||
foreach (var file in files)
|
||
{
|
||
// 如果传入了 fileFilter 函数,调用该函数进行筛选
|
||
if (fileFilter == null || fileFilter(file))
|
||
{
|
||
if (isDirectory == null || isDirectory == false)
|
||
{
|
||
// 如果指定了输出格式函数,则使用格式化函数;否则使用原始路径
|
||
result.Add(outputFormat == null ? file : outputFormat(file));
|
||
}
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
// 生成截图
|
||
public static PngBitmapEncoder CaptureWindowScreenshot(Window window, string? filePath = null)
|
||
{
|
||
// 获取当前窗口的 DPI 缩放因子
|
||
var dpiScale = VisualTreeHelper.GetDpi(window);
|
||
|
||
// 获取 DPI 缩放因子的 X 和 Y 值,通常 X 和 Y 应该是相等的
|
||
double dpiX = dpiScale.DpiScaleX;
|
||
double dpiY = dpiScale.DpiScaleY;
|
||
|
||
// 根据 DPI 缩放因子调整截图的尺寸
|
||
int width = (int)(window.ActualWidth * dpiX); // 使用 dpiX
|
||
int height = (int)(window.ActualHeight * dpiY); // 使用 dpiY
|
||
|
||
// 创建一个 RenderTargetBitmap 对象,并且考虑 DPI 缩放
|
||
RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, 96 * dpiX, 96 * dpiY, System.Windows.Media.PixelFormats.Pbgra32);
|
||
|
||
// 使用 VisualTreeHelper 进行渲染
|
||
rtb.Render(window);
|
||
|
||
// 创建一个 PngBitmapEncoder 来保存为 PNG 格式
|
||
PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
|
||
pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
|
||
|
||
if (!string.IsNullOrEmpty(filePath))
|
||
{
|
||
// 保存图像到文件
|
||
using (FileStream fs = new FileStream(filePath, FileMode.Create))
|
||
{
|
||
pngEncoder.Save(fs);
|
||
}
|
||
}
|
||
return pngEncoder;
|
||
}
|
||
#endregion
|
||
|
||
#region 任务操作
|
||
public static async Task<int> RunExternalCommand(string? applicationPath = "explorer.exe", string arguments="", bool UseShellExecute = false, bool CreateNoWindow = false)
|
||
{
|
||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||
{
|
||
FileName = applicationPath,
|
||
Arguments = arguments,
|
||
UseShellExecute = UseShellExecute,
|
||
CreateNoWindow = CreateNoWindow
|
||
};
|
||
|
||
try
|
||
{
|
||
Process process = Process.Start(startInfo) ??
|
||
throw new InvalidOperationException("Failed to start process.");
|
||
|
||
if (UseShellExecute != true)
|
||
{
|
||
await Task.Run(() => process.WaitForExit());
|
||
return process.ExitCode; // 返回进程的退出代码
|
||
}
|
||
else
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
}
|
||
|
||
catch (Exception ex)
|
||
{
|
||
throw;
|
||
}
|
||
}
|
||
|
||
public static async Task<string> RunExternalCommandResult(string applicationPath, string arguments, bool CreateNoWindow = true)
|
||
{
|
||
// 创建一个新的进程启动信息
|
||
ProcessStartInfo startInfo = new ProcessStartInfo
|
||
{
|
||
FileName = applicationPath,
|
||
Arguments = arguments,
|
||
UseShellExecute = false, // 必须设置为 false 以便能够重定向输入输出
|
||
RedirectStandardOutput = true, // 重定向标准输出
|
||
RedirectStandardError = true, // 可选:也重定向标准错误流
|
||
CreateNoWindow = CreateNoWindow // 不创建窗口
|
||
};
|
||
|
||
try
|
||
{
|
||
// 启动进程
|
||
using (Process process = new Process())
|
||
{
|
||
process.StartInfo = startInfo;
|
||
|
||
// 启动进程
|
||
process.Start();
|
||
|
||
// 读取输出流
|
||
string output = await process.StandardOutput.ReadToEndAsync();
|
||
string error = await process.StandardError.ReadToEndAsync(); // 读取标准错误流
|
||
|
||
// 等待进程结束
|
||
await process.WaitForExitAsync();
|
||
/*
|
||
if (process.ExitCode != 0)
|
||
{
|
||
// 处理非零退出代码的情况
|
||
throw new Exception($"Process exited with code {process.ExitCode}: {error}");
|
||
}
|
||
*/
|
||
|
||
return output; // 返回标准输出内容
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
// 可以记录或处理异常
|
||
throw; // 重新抛出异常以便调用者捕获
|
||
}
|
||
}
|
||
#endregion
|
||
|
||
// 通过 UDP 发送消息
|
||
public static void SendUdpMessage(string _serverIp, int _serverPort, string message)
|
||
{
|
||
try
|
||
{
|
||
using (UdpClient udpClient = new UdpClient())
|
||
{
|
||
IPEndPoint endPoint;
|
||
|
||
// 真正的自动识别:先尝试解析为IP地址,失败则当作域名处理
|
||
if (IPAddress.TryParse(_serverIp, out IPAddress ipAddress))
|
||
{
|
||
// 输入的是IP地址
|
||
endPoint = new IPEndPoint(ipAddress, _serverPort);
|
||
}
|
||
else
|
||
{
|
||
// 输入的是域名,进行DNS解析
|
||
IPAddress[] addresses = Dns.GetHostAddresses(_serverIp);
|
||
if (addresses.Length == 0)
|
||
{
|
||
Debug.WriteLine($"无法解析域名: {_serverIp}");
|
||
return;
|
||
}
|
||
endPoint = new IPEndPoint(addresses[0], _serverPort);
|
||
}
|
||
|
||
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
|
||
udpClient.Send(messageBytes, messageBytes.Length, endPoint);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"发送 UDP 消息失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
// 通过 TCP 发送消息
|
||
public static void SendTcpMessage(string _serverIp, int _serverPort, string message)
|
||
{
|
||
try
|
||
{
|
||
using (TcpClient tcpClient = new TcpClient(_serverIp, _serverPort))
|
||
using (NetworkStream networkStream = tcpClient.GetStream())
|
||
{
|
||
byte[] messageBytes = Encoding.UTF8.GetBytes(message);
|
||
networkStream.Write(messageBytes, 0, messageBytes.Length);
|
||
networkStream.Flush();
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Debug.WriteLine($"发送 TCP 消息失败: {ex.Message}");
|
||
}
|
||
}
|
||
|
||
// 生成哈希
|
||
public static string GenerateHash(string input)
|
||
{
|
||
// 创建SHA256对象
|
||
using (SHA256 sha256 = SHA256.Create())
|
||
{
|
||
// 将输入字符串转换为字节数组并计算哈希值
|
||
byte[] bytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
|
||
|
||
// 将哈希值转换为十六进制字符串
|
||
StringBuilder stringBuilder = new StringBuilder();
|
||
foreach (byte b in bytes)
|
||
{
|
||
stringBuilder.Append(b.ToString("x2"));
|
||
}
|
||
|
||
// 返回最终的哈希字符串
|
||
return stringBuilder.ToString();
|
||
}
|
||
}
|
||
}
|
||
}
|