解决了一些小问题

This commit is contained in:
2025-06-23 16:44:28 +08:00
parent 1b01f94bf3
commit 6498f0a220
2 changed files with 354 additions and 360 deletions

13
Form1.Designer.cs generated
View File

@@ -32,7 +32,6 @@
this.Path1_Box = new System.Windows.Forms.TextBox(); this.Path1_Box = new System.Windows.Forms.TextBox();
this.Choose1_Button = new System.Windows.Forms.Button(); this.Choose1_Button = new System.Windows.Forms.Button();
this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog(); this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label();
this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.Start_Button = new System.Windows.Forms.Button(); this.Start_Button = new System.Windows.Forms.Button();
@@ -73,14 +72,6 @@
this.Choose1_Button.UseVisualStyleBackColor = true; this.Choose1_Button.UseVisualStyleBackColor = true;
this.Choose1_Button.Click += new System.EventHandler(this.Choose1_Button_Click); this.Choose1_Button.Click += new System.EventHandler(this.Choose1_Button_Click);
// //
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 53);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(0, 12);
this.label1.TabIndex = 3;
//
// label2 // label2
// //
this.label2.AutoSize = true; this.label2.AutoSize = true;
@@ -174,10 +165,11 @@
this.Controls.Add(this.Start_Button); this.Controls.Add(this.Start_Button);
this.Controls.Add(this.progressBar1); this.Controls.Add(this.progressBar1);
this.Controls.Add(this.label2); this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Controls.Add(this.Choose1_Button); this.Controls.Add(this.Choose1_Button);
this.Controls.Add(this.Path1_Box); this.Controls.Add(this.Path1_Box);
this.Controls.Add(this.Path_Text); this.Controls.Add(this.Path_Text);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.Name = "MD5Create"; this.Name = "MD5Create";
this.Text = "MD5Create"; this.Text = "MD5Create";
this.ResumeLayout(false); this.ResumeLayout(false);
@@ -191,7 +183,6 @@
private System.Windows.Forms.TextBox Path1_Box; private System.Windows.Forms.TextBox Path1_Box;
private System.Windows.Forms.Button Choose1_Button; private System.Windows.Forms.Button Choose1_Button;
private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1; private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2; private System.Windows.Forms.Label label2;
private System.Windows.Forms.ProgressBar progressBar1; private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.Button Start_Button; private System.Windows.Forms.Button Start_Button;

701
Form1.cs
View File

@@ -1,350 +1,353 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Data; using System.Data;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using System.Xml; using System.Xml;
using Newtonsoft.Json; using Newtonsoft.Json;
using Microsoft.WindowsAPICodePack.Dialogs; using Microsoft.WindowsAPICodePack.Dialogs;
namespace MD5Create namespace MD5Create
{ {
public partial class MD5Create : Form public partial class MD5Create : Form
{ {
public MD5Create() public MD5Create()
{ {
InitializeComponent(); InitializeComponent();
// Initialize progress bar // 固定窗口启动位置为屏幕左上角
progressBar1.Minimum = 0; this.StartPosition = FormStartPosition.Manual;
progressBar1.Maximum = 100; this.Location = new Point(200, 200);
progressBar1.Value = 0; // Initialize progress bar
progressBar1.Step = 1; progressBar1.Minimum = 0;
} progressBar1.Maximum = 100;
progressBar1.Value = 0;
// 程序启动前检查目录和版本号 progressBar1.Step = 1;
private async void Start_Button_Click(object sender, EventArgs e) }
{
if (string.IsNullOrWhiteSpace(Path1_Box.Text)) // 程序启动前检查目录和版本号
{ private async void Start_Button_Click(object sender, EventArgs e)
MessageBox.Show("请先选择目录!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning); {
return; if (string.IsNullOrWhiteSpace(Path1_Box.Text))
} {
MessageBox.Show("请先选择目录!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
if (string.IsNullOrWhiteSpace(textBox1.Text)) return;
{ }
MessageBox.Show("请输入版本号!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return; if (string.IsNullOrWhiteSpace(textBox1.Text))
} {
MessageBox.Show("请输入版本号!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
// Reset progress bar return;
progressBar1.Value = 0; }
await Task.Run(() => GenerateMD5Json(Path1_Box.Text)); // Reset progress bar
} progressBar1.Value = 0;
private void Choose1_Button_Click(object sender, EventArgs e) await Task.Run(() => GenerateMD5Json(Path1_Box.Text));
{ }
// 使用 Windows API Code Pack 中的 CommonOpenFileDialog开启文件夹选择模式
using (var dialog = new CommonOpenFileDialog()) private void Choose1_Button_Click(object sender, EventArgs e)
{ {
dialog.Title = "请选择文件夹"; // 使用 Windows API Code Pack 中的 CommonOpenFileDialog开启文件夹选择模式
dialog.IsFolderPicker = true; // 文件夹选择模式 using (var dialog = new CommonOpenFileDialog())
dialog.AllowNonFileSystemItems = false; {
dialog.Title = "请选择文件夹";
if (!string.IsNullOrWhiteSpace(Path1_Box.Text) && Directory.Exists(Path1_Box.Text)) dialog.IsFolderPicker = true; // 文件夹选择模式
{ dialog.AllowNonFileSystemItems = false;
dialog.InitialDirectory = Path1_Box.Text; // 打开到当前路径
} if (!string.IsNullOrWhiteSpace(Path1_Box.Text) && Directory.Exists(Path1_Box.Text))
{
if (dialog.ShowDialog() == CommonFileDialogResult.Ok) dialog.InitialDirectory = Path1_Box.Text; // 打开到当前路径
{ }
Path1_Box.Text = dialog.FileName; // 选择的文件夹路径
} if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
} {
} Path1_Box.Text = dialog.FileName; // 选择的文件夹路径
}
private void Exit_Button_Click(object sender, EventArgs e) }
{ }
this.Close();
} private void Exit_Button_Click(object sender, EventArgs e)
{
// 计算 MD5 的值 this.Close();
private string MD5Generation(string filePath) }
{
using (var md5 = MD5.Create()) // 计算 MD5 的值
using (var stream = File.OpenRead(filePath)) private string MD5Generation(string filePath)
{ {
byte[] hash = md5.ComputeHash(stream); using (var md5 = MD5.Create())
return BitConverter.ToString(hash).Replace("-", "").ToLower(); using (var stream = File.OpenRead(filePath))
} {
} byte[] hash = md5.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLower();
// 获取目录中文件总数(用于进度计算) }
private int GetTotalFileCount(string directoryPath, string excludeFolder) }
{
int count = 0; // 获取目录中文件总数(用于进度计算)
try private int GetTotalFileCount(string directoryPath, string excludeFolder)
{ {
count += Directory.GetFiles(directoryPath).Length; int count = 0;
} try
catch (Exception) {
{ count += Directory.GetFiles(directoryPath).Length;
// 忽略无法访问的目录 }
} catch (Exception)
{
try // 忽略无法访问的目录
{ }
foreach (var dir in Directory.GetDirectories(directoryPath))
{ try
if (dir.Equals(excludeFolder, StringComparison.OrdinalIgnoreCase)) {
continue; foreach (var dir in Directory.GetDirectories(directoryPath))
{
// 跳过符号链接 / Junction if (dir.Equals(excludeFolder, StringComparison.OrdinalIgnoreCase))
var dirInfo = new DirectoryInfo(dir); continue;
if ((dirInfo.Attributes & FileAttributes.ReparsePoint) != 0)
continue; // 跳过符号链接 / Junction
var dirInfo = new DirectoryInfo(dir);
count += GetTotalFileCount(dir, excludeFolder); if ((dirInfo.Attributes & FileAttributes.ReparsePoint) != 0)
} continue;
}
catch (Exception) count += GetTotalFileCount(dir, excludeFolder);
{ }
// 同样忽略 }
} catch (Exception)
return count; {
} // 同样忽略
}
// 生成目录结构的 json 表示 return count;
private Dictionary<string, object> GenerateDirectoryJson(string directoryPath, string rootPath, int totalFiles, ref int processedFiles, string excludeFolder, string fileFolder) }
{
var filesDict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // 生成目录结构的 json 表示
var dirsDict = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase); private Dictionary<string, object> GenerateDirectoryJson(string directoryPath, string rootPath, int totalFiles, ref int processedFiles, string excludeFolder, string fileFolder)
{
// 处理当前目录文件 var filesDict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
string[] files; var dirsDict = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
try
{ // 处理当前目录文件
files = Directory.GetFiles(directoryPath); string[] files;
} try
catch (Exception ex) {
{ files = Directory.GetFiles(directoryPath);
Process_Box.BeginInvoke((MethodInvoker)(() => }
{ catch (Exception ex)
Process_Box.AppendText($"无法访问目录文件列表 {directoryPath}: {ex.Message}{Environment.NewLine}"); {
Process_Box.SelectionStart = Process_Box.Text.Length; Process_Box.BeginInvoke((MethodInvoker)(() =>
Process_Box.ScrollToCaret(); {
})); Process_Box.AppendText($"无法访问目录文件列表 {directoryPath}: {ex.Message}{Environment.NewLine}");
files = Array.Empty<string>(); Process_Box.SelectionStart = Process_Box.Text.Length;
} Process_Box.ScrollToCaret();
}));
foreach (var file in files) files = Array.Empty<string>();
{ }
string fileName = Path.GetFileName(file);
string fileMD5; foreach (var file in files)
try {
{ string fileName = Path.GetFileName(file);
fileMD5 = MD5Generation(file); string fileMD5;
} try
catch (Exception ex) {
{ fileMD5 = MD5Generation(file);
Process_Box.BeginInvoke((MethodInvoker)(() => }
{ catch (Exception ex)
Process_Box.AppendText($"计算MD5失败 {file}: {ex.Message}{Environment.NewLine}"); {
Process_Box.SelectionStart = Process_Box.Text.Length; Process_Box.BeginInvoke((MethodInvoker)(() =>
Process_Box.ScrollToCaret(); {
})); Process_Box.AppendText($"计算MD5失败 {file}: {ex.Message}{Environment.NewLine}");
continue; Process_Box.SelectionStart = Process_Box.Text.Length;
} Process_Box.ScrollToCaret();
}));
filesDict[fileName] = fileMD5; continue;
}
try
{ filesDict[fileName] = fileMD5;
string destPath = Path.Combine(fileFolder, fileMD5);
if (!File.Exists(destPath)) try
{ {
File.Copy(file, destPath, overwrite: false); string destPath = Path.Combine(fileFolder, fileMD5);
Process_Box.BeginInvoke((MethodInvoker)(() => if (!File.Exists(destPath))
{ {
Process_Box.AppendText($"已复制: {file} -> {destPath}{Environment.NewLine}"); File.Copy(file, destPath, overwrite: false);
Process_Box.SelectionStart = Process_Box.Text.Length; Process_Box.BeginInvoke((MethodInvoker)(() =>
Process_Box.ScrollToCaret(); {
})); Process_Box.AppendText($"已复制: {file} -> {destPath}{Environment.NewLine}");
} Process_Box.SelectionStart = Process_Box.Text.Length;
} Process_Box.ScrollToCaret();
catch (Exception ex) }));
{ }
Process_Box.BeginInvoke((MethodInvoker)(() => }
{ catch (Exception ex)
Process_Box.AppendText($"复制文件失败 {file}: {ex.Message}{Environment.NewLine}"); {
Process_Box.SelectionStart = Process_Box.Text.Length; Process_Box.BeginInvoke((MethodInvoker)(() =>
Process_Box.ScrollToCaret(); {
})); Process_Box.AppendText($"复制文件失败 {file}: {ex.Message}{Environment.NewLine}");
} Process_Box.SelectionStart = Process_Box.Text.Length;
Process_Box.ScrollToCaret();
// 更新进度条 }));
processedFiles++; }
int progress = (int)((double)processedFiles / totalFiles * 100);
progressBar1.Invoke((MethodInvoker)(() => // 更新进度条
{ processedFiles++;
progressBar1.Value = Math.Min(progress, progressBar1.Maximum); int progress = (int)((double)processedFiles / totalFiles * 100);
})); progressBar1.Invoke((MethodInvoker)(() =>
{
// 显示处理路径 progressBar1.Value = Math.Min(progress, progressBar1.Maximum);
string relativePath = GetRelativePath(file, rootPath); }));
Process_Box.BeginInvoke((MethodInvoker)(() =>
{ // 显示处理路径
Process_Box.AppendText($".\\{relativePath}{Environment.NewLine}"); string relativePath = GetRelativePath(file, rootPath);
Process_Box.SelectionStart = Process_Box.Text.Length; Process_Box.BeginInvoke((MethodInvoker)(() =>
Process_Box.ScrollToCaret(); {
})); Process_Box.AppendText($".\\{relativePath}{Environment.NewLine}");
} Process_Box.SelectionStart = Process_Box.Text.Length;
Process_Box.ScrollToCaret();
// 递归处理子目录 }));
string[] subDirs; }
try
{ // 递归处理子目录
subDirs = Directory.GetDirectories(directoryPath); string[] subDirs;
} try
catch (Exception ex) {
{ subDirs = Directory.GetDirectories(directoryPath);
Process_Box.BeginInvoke((MethodInvoker)(() => }
{ catch (Exception ex)
Process_Box.AppendText($"无法访问子目录列表 {directoryPath}: {ex.Message}{Environment.NewLine}"); {
Process_Box.SelectionStart = Process_Box.Text.Length; Process_Box.BeginInvoke((MethodInvoker)(() =>
Process_Box.ScrollToCaret(); {
})); Process_Box.AppendText($"无法访问子目录列表 {directoryPath}: {ex.Message}{Environment.NewLine}");
subDirs = Array.Empty<string>(); Process_Box.SelectionStart = Process_Box.Text.Length;
} Process_Box.ScrollToCaret();
}));
foreach (var dir in subDirs) subDirs = Array.Empty<string>();
{ }
if (Path.GetFullPath(dir).Equals(Path.GetFullPath(excludeFolder), StringComparison.OrdinalIgnoreCase))
continue; foreach (var dir in subDirs)
{
// 跳过符号链接 / Junction if (Path.GetFullPath(dir).Equals(Path.GetFullPath(excludeFolder), StringComparison.OrdinalIgnoreCase))
var dirInfo = new DirectoryInfo(dir); continue;
if ((dirInfo.Attributes & FileAttributes.ReparsePoint) != 0)
continue; // 跳过符号链接 / Junction
var dirInfo = new DirectoryInfo(dir);
string dirName = Path.GetFileName(dir); if ((dirInfo.Attributes & FileAttributes.ReparsePoint) != 0)
dirsDict[dirName] = GenerateDirectoryJson(dir, rootPath, totalFiles, ref processedFiles, excludeFolder, fileFolder); continue;
}
string dirName = Path.GetFileName(dir);
var result = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) dirsDict[dirName] = GenerateDirectoryJson(dir, rootPath, totalFiles, ref processedFiles, excludeFolder, fileFolder);
{ }
{ "files", filesDict },
{ "dirs", dirsDict } var result = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
}; {
{ "files", filesDict },
return result; { "dirs", dirsDict }
} };
// 获取相对路径 return result;
private string GetRelativePath(string fullPath, string basePath) }
{
if (!basePath.EndsWith(Path.DirectorySeparatorChar.ToString())) // 获取相对路径
basePath += Path.DirectorySeparatorChar; private string GetRelativePath(string fullPath, string basePath)
{
Uri baseUri = new Uri(basePath); if (!basePath.EndsWith(Path.DirectorySeparatorChar.ToString()))
Uri fullUri = new Uri(fullPath); basePath += Path.DirectorySeparatorChar;
return Uri.UnescapeDataString(baseUri.MakeRelativeUri(fullUri).ToString()
.Replace('/', Path.DirectorySeparatorChar)); Uri baseUri = new Uri(basePath);
} Uri fullUri = new Uri(fullPath);
return Uri.UnescapeDataString(baseUri.MakeRelativeUri(fullUri).ToString()
// 生成 json 文件 .Replace('/', Path.DirectorySeparatorChar));
private void GenerateMD5Json(string rootDirectory) }
{
if (!Directory.Exists(rootDirectory)) // 生成 json 文件
{ private void GenerateMD5Json(string rootDirectory)
this.Invoke((MethodInvoker)(() => {
{ if (!Directory.Exists(rootDirectory))
MessageBox.Show("指定的目录不存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); {
})); this.Invoke((MethodInvoker)(() =>
return; {
} MessageBox.Show("指定的目录不存在!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}));
try return;
{ }
this.Invoke((MethodInvoker)(() =>
{ try
Process_Box.Clear(); {
progressBar1.Value = 0; this.Invoke((MethodInvoker)(() =>
})); {
Application.DoEvents(); Process_Box.Clear();
progressBar1.Value = 0;
// 存储MD5值 }));
string md5FolderPath = Path.Combine(rootDirectory, "MD5"); Application.DoEvents();
Directory.CreateDirectory(md5FolderPath);
// 存储MD5值对应的文件 // 存储MD5值
string fileFolderPath = Path.Combine(md5FolderPath, "File"); string md5FolderPath = Path.Combine(rootDirectory, "MD5");
Directory.CreateDirectory(fileFolderPath); Directory.CreateDirectory(md5FolderPath);
// 存储MD5值对应的文件
int totalFiles = GetTotalFileCount(rootDirectory, md5FolderPath); string fileFolderPath = Path.Combine(md5FolderPath, "File");
int processedFiles = 0; Directory.CreateDirectory(fileFolderPath);
// 如果文件数量为0直接设置进度为100% int totalFiles = GetTotalFileCount(rootDirectory, md5FolderPath);
if (totalFiles == 0) int processedFiles = 0;
{
progressBar1.Value = 100; // 如果文件数量为0直接设置进度为100%
Process_Box.AppendText("没有找到任何文件\n"); if (totalFiles == 0)
return; {
} progressBar1.Value = 100;
Process_Box.AppendText("没有找到任何文件\n");
var directoryStructure = GenerateDirectoryJson(rootDirectory, rootDirectory, totalFiles, ref processedFiles, md5FolderPath, fileFolderPath); return;
}
// 创建包含版本号的新结构
var versionedStructure = new Dictionary<string, object> var directoryStructure = GenerateDirectoryJson(rootDirectory, rootDirectory, totalFiles, ref processedFiles, md5FolderPath, fileFolderPath);
{
{ "version", textBox1.Text.Trim() }, // 创建包含版本号的新结构
{ "data", directoryStructure } var versionedStructure = new Dictionary<string, object>
}; {
{ "version", textBox1.Text.Trim() },
// 序列化和保存JSON { "data", directoryStructure }
string json = JsonConvert.SerializeObject(versionedStructure, Newtonsoft.Json.Formatting.Indented); };
string jsonMD5 = CalculateMD5FromString(json);
string outputPath = Path.Combine(md5FolderPath, "md5.json"); // 序列化和保存JSON
File.WriteAllText(outputPath, json); string json = JsonConvert.SerializeObject(versionedStructure, Newtonsoft.Json.Formatting.Indented);
string jsonMD5 = CalculateMD5FromString(json);
// 最终更新 string outputPath = Path.Combine(md5FolderPath, "md5.json");
this.Invoke((MethodInvoker)(() => File.WriteAllText(outputPath, json);
{
progressBar1.Value = 100; // 最终更新
Process_Box.AppendText($"\nmd5.json文件已生成在{outputPath}\n"); this.Invoke((MethodInvoker)(() =>
Process_Box.AppendText($"JSON内容MD5校验值{jsonMD5}"); {
Process_Box.ScrollToCaret(); progressBar1.Value = 100;
})); Process_Box.AppendText($"\nmd5.json文件已生成在{outputPath}\n");
} Process_Box.AppendText($"JSON内容MD5校验值{jsonMD5}");
catch (Exception ex) Process_Box.ScrollToCaret();
{ }));
this.Invoke((MethodInvoker)(() => }
{ catch (Exception ex)
MessageBox.Show($"生成JSON文件时出错{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error); {
})); this.Invoke((MethodInvoker)(() =>
} {
} MessageBox.Show($"生成JSON文件时出错{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}));
// 计算字符串的MD5值 }
private string CalculateMD5FromString(string input) }
{
using (var md5 = MD5.Create()) // 计算字符串的MD5值
{ private string CalculateMD5FromString(string input)
byte[] inputBytes = Encoding.UTF8.GetBytes(input); {
byte[] hashBytes = md5.ComputeHash(inputBytes); using (var md5 = MD5.Create())
{
StringBuilder sb = new StringBuilder(); byte[] inputBytes = Encoding.UTF8.GetBytes(input);
for (int i = 0; i < hashBytes.Length; i++) byte[] hashBytes = md5.ComputeHash(inputBytes);
{
sb.Append(hashBytes[i].ToString("x2")); // 使用小写十六进制格式 StringBuilder sb = new StringBuilder();
} for (int i = 0; i < hashBytes.Length; i++)
return sb.ToString(); {
} sb.Append(hashBytes[i].ToString("x2")); // 使用小写十六进制格式
} }
} return sb.ToString();
}
}
}
} }