using HalconDotNet; using Microsoft.Win32; using LB_SmartVision; using SharpCompress.Common; using System.Collections.Concurrent; using System.Configuration; using System.Diagnostics; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace LB_SmartVision.Tool { public sealed class Tool : IDisposable { // 静态构造函数启动消费者任务 static Tool() { // 启动消费者任务 _logConsumerTask = Task.Factory.StartNew( () => ProcessLogQueue(_logCts.Token), _logCts.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default); // FIFO 行为,超出容量时阻塞 _RealImageQueue = new BlockingCollection(capacity); _RealImageCts = new CancellationTokenSource(); StartRealImageConsumer(); } public void Dispose() { try { // 停止接受新日志 _logQueue.CompleteAdding(); // 取消正在进行的操作 _logCts.Cancel(); // 等待消费者完成 if (!_logConsumerTask.Wait(TimeSpan.FromSeconds(5))) { Debug.WriteLine("日志消费者线程关闭超时"); } _RealImageCts.Cancel(); _RealImageQueue.CompleteAdding(); while (_RealImageQueue.TryTake(out var task)) { if (task.Image is Bitmap bitmap) { bitmap.Dispose(); } else if (task.Image is HObject hobject) { hobject.Dispose(); } } _RealImageCts.Dispose(); _RealImageQueue.Dispose(); _RealImageConsumerTask?.Dispose(); } catch { } finally { _logCts.Dispose(); _logQueue.Dispose(); } } #region 日志功能 public static string _logFilePath = Path.Combine(GlobalVar.strPathLog, $"{GlobalVar.strStartTime}.log"); public static string _logFilePathBackup = Path.Combine(GlobalVar.strPathLog, $"{GlobalVar.strStartTime}(副本).log"); private static readonly BlockingCollection _logQueue = new BlockingCollection(1024); private static readonly CancellationTokenSource _logCts = new CancellationTokenSource(); private static Task _logConsumerTask; private static readonly object _fileLock = new object(); // 添加日志到队列 public static bool AddLog(string message) { if (!_logQueue.IsAddingCompleted) { try { _logQueue.Add(message, _logCts.Token); return true; } catch (InvalidOperationException) { // 队列已关闭 return false; } } return false; } // 消费者任务处理队列 private static void ProcessLogQueue(CancellationToken ct) { try { foreach (var logEntry in _logQueue.GetConsumingEnumerable(ct)) { lock (_fileLock) { try { File.AppendAllText(_logFilePath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {logEntry}{Environment.NewLine}"); } catch { try { // 日志写入失败二次尝试 File.AppendAllText(_logFilePath, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {logEntry}{Environment.NewLine}"); } catch { try { // 日志写入失败处理(可添加到备用队列或控制台输出) File.AppendAllText(_logFilePathBackup, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {logEntry}{Environment.NewLine}"); } catch (Exception ex) { Debug.WriteLine($"日志写入失败: {ex.Message}"); } } } } } } catch (OperationCanceledException) { // 正常取消 } } // 尝试写入文件的辅助方法 private static bool TryWriteToFile(string path, byte[] data) { try { using (var stream = new FileStream( path, FileMode.Append, FileAccess.Write, FileShare.ReadWrite, bufferSize: 4096, useAsync: true)) { stream.Write(data, 0, data.Length); return true; } } catch { return false; } } #endregion #region 存原图功能 /// /// 超出容量时阻塞 /// private static readonly BlockingCollection _RealImageQueue; private static readonly CancellationTokenSource _RealImageCts; private static Task _RealImageConsumerTask; private static int _restartCount; private const int MaxRestarts = 5; private static int capacity = 10; // 队列容量 // 获取指定图像格式的编码器信息 private static ImageCodecInfo GetEncoder(ImageFormat format) { // 获取所有已安装的图像编码器 ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); // 查找匹配指定格式的编码器 return codecs.FirstOrDefault(codec => codec.FormatID == format.Guid); } public static long _imageQuality = 100L; static ImageCodecInfo jpegEncoder = null; static EncoderParameters encoderParams = null; static char[] invalidChars = Path.GetInvalidFileNameChars(); // 图片保存任务结构 public struct ImageSaveTask { public object Image { get; set; } public string FullPath { get; set; } public string ImageType { get; set; } public long Quality { get; set; } public ImageSaveTask(object image, string fullPath, string imageType = "jpg", long quality = 50L) { Image = image; FullPath = fullPath; ImageType = imageType.ToLower(); Quality = quality; } } private static void StartRealImageConsumer() { _RealImageConsumerTask = Task.Run(async () => { try { await RealImageProcessQueue(); } catch when (_RealImageCts.IsCancellationRequested) { // 正常关闭 } catch (Exception ex) { if (++_restartCount <= MaxRestarts) { StartRealImageConsumer(); // 自动重启 } AddLog($"保存图片StartRealImageConsumer出现异常:{ex.Message}"); } }, _RealImageCts.Token); } private static async Task RealImageProcessQueue() { foreach (var task in _RealImageQueue.GetConsumingEnumerable(_RealImageCts.Token)) { try { await SaveImageAsync(task); } catch (Exception ex) { AddLog($"保存图片RealImageProcessQueue出现异常:{ex.Message}"); } finally { if (task.Image != null) { if (task.Image is Bitmap bitmap) { bitmap.Dispose(); } if (task.Image is HObject hobject) { hobject.Dispose(); } } } } } public static void AddRealImage(object image, string filePath, string fileName, string imageType = "jpg", long quality = 50L) { if (_RealImageCts.IsCancellationRequested) throw new InvalidOperationException("Processor is shutting down"); if (IsSave(filePath)) { string fullPath = Path.Combine(filePath, $"{fileName}.{imageType.ToLower()}"); // FIFO 行为,超出容量时阻塞 //// 缓存图片大于容量说明磁盘存储不过来了,取出所有元素直到队列为空 //if (_RealImageQueue.Count >= capacity + 1) //{ // AddLog("缓存图片超过10张,清空已经缓存的旧图片"); // while (_RealImageQueue.TryTake(out _)) { } //} if (image is HObject hObject) { _RealImageQueue.Add(new ImageSaveTask { Image = hObject.Clone(), FullPath = fullPath, ImageType = imageType.ToLower(), Quality = quality }, _RealImageCts.Token); } else if (image is Bitmap bitmap) { _RealImageQueue.Add(new ImageSaveTask { Image = bitmap.Clone(), FullPath = fullPath, ImageType = imageType.ToLower(), Quality = quality }, _RealImageCts.Token); } } } // 程序启动时初始化编码器缓存 private static readonly Dictionary _encoderCache = ImageCodecInfo.GetImageEncoders() .ToDictionary(codec => codec.FormatID); // 通过ImageFormat获取编码器 private static ImageCodecInfo GetEncoderByFormat(ImageFormat format) { _encoderCache.TryGetValue(format.Guid, out var encoder); return encoder; } // 通过字符串类型获取编码器 private static ImageCodecInfo GetEncoderByType(string imageType) { var format = GetImageFormat(imageType); return GetEncoderByFormat(format); } // 获取ImageFormat的辅助方法 private static ImageFormat GetImageFormat(string imageType) { switch (imageType.ToLowerInvariant()) { case "jpg": case "jpeg": return ImageFormat.Jpeg; case "png": return ImageFormat.Png; case "bmp": return ImageFormat.Bmp; case "gif": return ImageFormat.Gif; case "tif": case "tiff": return ImageFormat.Tiff; default: throw new NotSupportedException($"不支持的图片格式: {imageType}"); } } private static async Task SaveImageAsync(ImageSaveTask task) { try { // 参数校验 if (task.Image == null) throw new ArgumentNullException(nameof(task.Image)); if (string.IsNullOrWhiteSpace(task.FullPath)) throw new ArgumentException("Invalid file path"); var dir = Path.GetDirectoryName(task.FullPath); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (task.Image is HObject hObject && hObject.IsInitialized()) { try { //Halcon存图需要用斜杠 task.FullPath.Replace("\\", "/"); HOperatorSet.WriteImage(hObject, task.ImageType, 0, task.FullPath); } catch { AddLog("保存图片时HOperatorSet.WriteImage发生异常"); } } else if (task.Image is Bitmap bitmap) { // 获取对应格式的编码器 ImageCodecInfo encoder = GetEncoderByType(task.ImageType); // 配置编码参数 var encoderParams = new EncoderParameters(1); encoderParams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, task.Quality); // 使用内存流中转避免文件锁冲突 using (var memoryStream = new MemoryStream()) { // 同步编码转异步操作(线程池优化) await Task.Run(() => { bitmap.Save(memoryStream, encoder, encoderParams); memoryStream.Position = 0; // 重置流位置 }).ConfigureAwait(false); // 原子性写入(临时文件+替换) var tempPath = $"{task.FullPath}.{Guid.NewGuid()}.tmp"; // 异步文件写入(带缓冲区优化) using (var fileStream = new FileStream( tempPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 81920, // 80KB缓冲区 useAsync: true)) { await memoryStream.CopyToAsync(fileStream) .ConfigureAwait(false); } // 原子替换文件(跨平台兼容) File.Move(tempPath, task.FullPath); } } } catch (Exception ex) when (IsRetryableException(ex)) { AddLog($"保存图片IsRetryableException出现异常:{ex.Message}"); } catch (Exception ex) { AddLog($"保存图片SaveImageAsync出现异常:{ex.Message}"); } } // 判断是否可重试的异常 private static bool IsRetryableException(Exception ex) { return ex is IOException or UnauthorizedAccessException or TimeoutException; } #endregion #region 磁盘回收功能 public static double MinSpace = 10; /// /// 获取磁盘剩余空间 /// /// /// public static double GetHardDiskFreeSpace(string strPath) { //磁盘名称 string strHardDiskName = strPath.Substring(0, 1); //获取C盘的剩余空间 DriveInfo cDrive = new DriveInfo(strHardDiskName); // 检查驱动器是否是有效的 if (cDrive.IsReady) { // 获取剩余空间 long freeSpace = cDrive.AvailableFreeSpace; // 将字节数转换为GB单位 return (double)freeSpace / (1024 * 1024 * 1024); } else { return 0; } } /// /// 判断是否允许保存 /// /// 保存文件的完整路径 /// public static bool IsSave(string fullPath) { // 获取上一级目录(父目录) string parentDirectory = Path.GetDirectoryName(fullPath); if (GetHardDiskFreeSpace(parentDirectory) >= MinSpace) return true; else { if (DeletOutTimeFiles(parentDirectory)) { // 删除超期文件后再次判断容量能否存储 if (GetHardDiskFreeSpace(parentDirectory) >= MinSpace) return true; return false; } else return false; } } /// ///删除超出时间的文件夹路径 /// /// /// public static bool DeletOutTimeFiles(string directoryPath, int days = 30) { try { // 保存时间不超过30天 DateTime NowTime = DateTime.Now; // 当前日期作为截止日期 DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath); DirectoryInfo[] directories = directoryInfo.GetDirectories(); for (int i = 0; i < directories.Length; i++) { if (directories[i].CreationTime.AddDays(days) < NowTime) { try { Directory.Delete(directories[i].FullName, recursive: true); Debug.WriteLine($"Deleted {directories[i].FullName}"); } catch (Exception ex) { // 可以选择在这里记录日志继续处理下一个文件 Debug.WriteLine($"Error deleting {directories[i].FullName}: {ex.Message}"); } } } AddLog($"磁盘空间不足,已删除路径[{directoryPath}]超过{days}天的文件,累计{directories.Length}个!"); return true; } catch { return false; } } #endregion public static bool ContainsChinese(string text) { if (string.IsNullOrEmpty(text)) { return false; } return Regex.IsMatch(text, @"[\u4e00-\u9fa5]"); } /// /// 保存CSV到本地 /// /// /// public static void WriteDataToFile(string fileDirectoryAndName, object[] obj) { try { string text = ""; // 写入CSV文件 using (var streamWriter = new StreamWriter(fileDirectoryAndName, true, Encoding.UTF8)) { for (int i = 0; i < obj.Length; i++) { text += (obj[i].ToString().Replace(",", ",")); if (i < obj.Length - 1) { text += ","; } } streamWriter.Write(text); streamWriter.WriteLine(); // 写入换行符 } } catch { } } /// /// 保存数据到本地 /// /// /// /// /// /// public static void SaveData(string filePath, List DataTitle, Dictionary resultData) { try { if (resultData.Count <= 0 || resultData == null) { return; } var dir = Path.GetDirectoryName(filePath); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (!File.Exists(filePath)) { WriteDataToFile(filePath, DataTitle.ToArray()); } List SaveData = new List(); foreach (var item in DataTitle) { if (resultData.ContainsKey(item)) { double dData = 0; if (double.TryParse(resultData[item].ToString(), out dData)) { SaveData.Add(dData.ToString("F2")); } else { SaveData.Add((resultData[item]?.ToString()).Replace(",", ",").ToString()); } } else SaveData.Add("NULL"); } try { WriteDataToFile(filePath, SaveData.ToArray()); } catch (Exception ex) { //文件被占用保存到副本中 try { //再次尝试写入 WriteDataToFile(filePath, SaveData.ToArray()); } catch { //写入失败写到副本中 filePath = AddCopySuffix(filePath, "(副本)"); if (!File.Exists(filePath)) { WriteDataToFile(filePath, DataTitle.ToArray()); } WriteDataToFile(filePath, SaveData.ToArray()); } } } catch (Exception ex) { AddLog("生产数据保存失败,原因是:" + ex.ToString()); } } public static string AddCopySuffix(string filePath, string suffix = "(副本)") { if (string.IsNullOrEmpty(filePath)) { return filePath; } string directory = Path.GetDirectoryName(filePath); string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filePath); string extension = Path.GetExtension(filePath); return Path.Combine(directory, $"{fileNameWithoutExtension}({suffix}){extension}"); } /// /// 加密文件 /// /// /// /// /// public static void EncryptFile(string inputFilePath, string outputFilePath, string key = "", string iv = "") { using (Aes aes = Aes.Create()) { if (key != "") { aes.Key = Convert.FromBase64String(key); aes.IV = Convert.FromBase64String(iv); } else { aes.Key = new byte[32]; aes.IV = new byte[16]; } using (FileStream outputFileStream = new FileStream(outputFilePath, FileMode.Create)) using (ICryptoTransform encryptor = aes.CreateEncryptor()) using (CryptoStream cryptoStream = new CryptoStream(outputFileStream, encryptor, CryptoStreamMode.Write)) using (FileStream inputFileStream = new FileStream(inputFilePath, FileMode.Open)) { inputFileStream.CopyTo(cryptoStream); } } } /// /// 解密文件 /// /// /// /// /// public static void DecryptFile(string inputFilePath, string outputFilePath, string key = "", string iv = "") { using (Aes aes = Aes.Create()) { if (key != "") { aes.Key = Convert.FromBase64String(key); aes.IV = Convert.FromBase64String(iv); } else { aes.Key = new byte[32]; aes.IV = new byte[16]; } using (FileStream inputFileStream = new FileStream(inputFilePath, FileMode.Open)) using (ICryptoTransform decryptor = aes.CreateDecryptor()) using (CryptoStream cryptoStream = new CryptoStream(inputFileStream, decryptor, CryptoStreamMode.Read)) using (FileStream outputFileStream = new FileStream(outputFilePath, FileMode.Create)) { cryptoStream.CopyTo(outputFileStream); } } } #region 加密狗 private const string DOG_AES_SALT = "MYAPP_KEY_SALT"; private const string DOG_AES_KEY = "MYAPP_AES_KEY"; private const string DOG_AES_IV = "MYAPP_AES_IV"; private const string REGISTRY_PATH = @"SOFTWARE\MyApp\SoftDog"; private static bool SetRegistryValue(RegistryKey baseKey, string valueName, string value) { try { using (RegistryKey key = baseKey.CreateSubKey(REGISTRY_PATH, RegistryKeyPermissionCheck.ReadWriteSubTree)) { if (key != null) { key.SetValue(valueName, value, RegistryValueKind.String); return true; } } } catch (SecurityException) { // 权限不足,正常情况 } catch (Exception ex) { Debug.WriteLine($"设置注册表值失败: {ex.Message}"); } return false; } private static string GetRegistryValue(string valueName) { // 先尝试HKLM string value = GetRegistryValue(Registry.LocalMachine, valueName); if (!string.IsNullOrEmpty(value)) { return value; } // 再尝试HKCU return GetRegistryValue(Registry.CurrentUser, valueName); } private static string GetRegistryValue(RegistryKey baseKey, string valueName) { try { using (RegistryKey key = baseKey.OpenSubKey(REGISTRY_PATH, false)) { return key?.GetValue(valueName) as string; } } catch { return null; } } /// /// 获取AES加密参数 /// public static (byte[] Key, byte[] IV) GetAesParameters() { try { string keyBase64 = GetRegistryValue(DOG_AES_KEY); string ivBase64 = GetRegistryValue(DOG_AES_IV); // 如果系统级没有,尝试用户级 if (!string.IsNullOrEmpty(keyBase64) && !string.IsNullOrEmpty(ivBase64)) { byte[] key = Convert.FromBase64String(keyBase64); byte[] iv = Convert.FromBase64String(ivBase64); return (key, iv); } return (null, null); } catch (Exception ex) { Debug.WriteLine($"获取AES参数失败: {ex.Message}"); return (null, null); } } /// /// 验证加密狗 /// public static bool ValidateAesDog() { var (key, iv) = GetAppBoundKey("VisionUltra"); if (key == null || iv == null) return false; // 验证密钥和IV的格式和长度 return key.Length == 32 && iv.Length == 16; // AES-256: 32字节密钥, 16字节IV } /// /// 生成与应用绑定的AES加密狗 /// public static bool GenerateAppBoundDog(string appIdentifier) { try { using (Aes aes = Aes.Create()) { aes.GenerateKey(); aes.GenerateIV(); // 使用应用标识符作为盐值 byte[] salt = Encoding.UTF8.GetBytes(appIdentifier); // 加密密钥本身(可选的安全增强) byte[] encryptedKey = EncryptKeyWithSalt(aes.Key, salt, aes.IV); // 存储加密后的密钥和盐值 string encryptedKeyBase64 = Convert.ToBase64String(encryptedKey); string saltBase64 = Convert.ToBase64String(salt); string ivBase64 = Convert.ToBase64String(aes.IV); bool success = SetRegistryValue(Registry.CurrentUser, DOG_AES_KEY, encryptedKeyBase64); success &= SetRegistryValue(Registry.CurrentUser, DOG_AES_SALT, saltBase64); success &= SetRegistryValue(Registry.CurrentUser, DOG_AES_IV, ivBase64); return success; } } catch (Exception ex) { Debug.WriteLine($"生成应用绑定加密狗失败: {ex.Message}"); return false; } } /// /// 验证并获取应用绑定密钥 /// public static (byte[] Key, byte[] IV) GetAppBoundKey(string expectedAppIdentifier) { try { string encryptedKeyBase64 = GetRegistryValue(DOG_AES_KEY); string saltBase64 = GetRegistryValue(DOG_AES_SALT); string ivBase64 = GetRegistryValue(DOG_AES_IV); if (string.IsNullOrEmpty(encryptedKeyBase64) || string.IsNullOrEmpty(saltBase64) || string.IsNullOrEmpty(ivBase64)) { return (null, null); } byte[] encryptedKey = Convert.FromBase64String(encryptedKeyBase64); byte[] salt = Convert.FromBase64String(saltBase64); byte[] iv = Convert.FromBase64String(ivBase64); // 验证应用标识符 string storedAppIdentifier = Encoding.UTF8.GetString(salt); if (storedAppIdentifier != expectedAppIdentifier) { return (null, null); } // 解密密钥 byte[] key = DecryptKeyWithSalt(encryptedKey, salt, iv); return (key, iv); } catch (Exception ex) { Debug.WriteLine($"获取应用绑定密钥失败: {ex.Message}"); return (null, null); } } private static byte[] EncryptKeyWithSalt(byte[] key, byte[] salt, byte[] iv) { using (var deriveBytes = new Rfc2898DeriveBytes(key, salt, 10000, HashAlgorithmName.SHA256)) { byte[] derivedKey = deriveBytes.GetBytes(32); // AES-256 // 这里可以添加额外的加密逻辑 return derivedKey; } } private static byte[] DecryptKeyWithSalt(byte[] encryptedKey, byte[] salt, byte[] iv) { // 反向解密过程 using (var deriveBytes = new Rfc2898DeriveBytes(encryptedKey, salt, 10000, HashAlgorithmName.SHA256)) { return deriveBytes.GetBytes(32); } } /// /// 使用加密狗中的密钥加密数据 /// public static string EncryptWithDog(string plainText) { var (key, iv) = GetAesParameters(); if (key == null || iv == null) throw new InvalidOperationException("未找到有效的加密狗"); using (Aes aes = Aes.Create()) { aes.Key = key; aes.IV = iv; ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); using (var ms = new MemoryStream()) using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) { using (var sw = new StreamWriter(cs)) { sw.Write(plainText); } return Convert.ToBase64String(ms.ToArray()); } } } /// /// 使用加密狗中的密钥解密数据 /// public static string DecryptWithDog(string cipherText) { var (key, iv) = GetAesParameters(); if (key == null || iv == null) throw new InvalidOperationException("未找到有效的加密狗"); using (Aes aes = Aes.Create()) { aes.Key = key; aes.IV = iv; ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); byte[] cipherBytes = Convert.FromBase64String(cipherText); using (var ms = new MemoryStream(cipherBytes)) using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read)) using (var sr = new StreamReader(cs)) { return sr.ReadToEnd(); } } } /// /// 注册加密狗 /// public static bool RegistrationDog() { Debug.WriteLine("正在生成AES加密狗..."); if (GenerateAppBoundDog("VisionUltra")) { Debug.WriteLine("AES加密狗生成成功!"); // 建议用户备份这些值 Debug.WriteLine("\n请妥善保存以上密钥信息!"); return true; } else { Debug.WriteLine("加密狗生成失败,请以管理员身份运行"); return false; } } /// /// 检查软加密狗 /// /// public static bool CheckDog() { if (!ValidateAesDog()) { Debug.WriteLine("未找到有效的AES加密狗"); return false; } Debug.WriteLine("AES加密狗验证成功"); return true; } #endregion /// /// 复制文件夹及其内容 /// /// /// /// public static bool CopyDirectory(string sourceDir, string destDir) { try { // 检查目标文件夹是否存在,如果不存在,则创建它 if (!Directory.Exists(destDir)) { Directory.CreateDirectory(destDir); } // 复制所有文件到目标文件夹 foreach (string file in Directory.GetFiles(sourceDir)) { string destFile = Path.Combine(destDir, Path.GetFileName(file)); File.Copy(file, destFile, true); // 第三个参数为 true,表示如果文件已存在,则覆盖它 } // 递归复制所有子文件夹 foreach (string subDir in Directory.GetDirectories(sourceDir)) { string destSubDir = Path.Combine(destDir, Path.GetFileName(subDir)); CopyDirectory(subDir, destSubDir); // 递归调用复制子文件夹 } return true; } catch { return false; } } /// /// 重命名文件夹 /// /// /// /// public static bool RenameDirectory(string oldDir, string newDir) { try { // 重命名文件夹 if (Directory.Exists(oldDir)) { Directory.Move(oldDir, newDir); return true; } Debug.WriteLine($"文件不存在: {oldDir}"); return false; } catch { return false; } } /// /// 重命名文件 /// /// /// /// public static bool RenameFile(string oldFile, string newFile) { try { if (!File.Exists(newFile)) { // 重命名文件 File.Move(oldFile, newFile); Debug.WriteLine($"文件已重命名: {oldFile} -> {newFile}"); return true; } Debug.WriteLine($"文件不存在: {oldFile}"); return false; } catch { return false; } } #region 读写到exe.Config文件 public static void WriteConfig(string node, string value) { System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); if (config.AppSettings.Settings[node] == null) { config.AppSettings.Settings.Add(node, value); } else { config.AppSettings.Settings[node].Value = value; } config.Save(ConfigurationSaveMode.Modified); ConfigurationManager.RefreshSection("appSettings");//重新加载新的配置文件 } public static bool ReadStringConfig(string node, out string result) { result = ""; try { if (ConfigurationManager.AppSettings != null && ConfigurationManager.AppSettings.Count > 0 && ConfigurationManager.AppSettings.AllKeys.Contains(node)) { result = ConfigurationManager.AppSettings[node].ToString(); if (result == null) { WriteConfig(node, ""); result = ""; return false; } else { return true; } } else { return false; } } catch { WriteConfig(node, ""); result = ""; return false; } } public static bool ReadBoolenConfig(string node, out bool result) { result = false; try { result = Convert.ToBoolean(ConfigurationManager.AppSettings[node]); if (result == null) { WriteConfig(node, (false).ToString()); result = false; return false; } else { return true; } } catch { WriteConfig(node, (false).ToString()); result = false; return false; } } #endregion } }