解决了一些小问题

This commit is contained in:
2025-06-30 22:29:53 +08:00
parent e2b7855f48
commit e11a68e9b8
5 changed files with 440 additions and 1 deletions

3
FodyWeavers.xml Normal file
View File

@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<Costura />
</Weavers>

176
FodyWeavers.xsd Normal file
View File

@@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:all>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>Obsolete, use UnmanagedWinX86Assemblies instead</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinX86Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged X86 (32 bit) assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>Obsolete, use UnmanagedWinX64Assemblies instead.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinX64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged X64 (64 bit) assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="UnmanagedWinArm64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged Arm64 (64 bit) assembly names to include, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:all>
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeReferences" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls if runtime assemblies are also embedded.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseRuntimeReferencePaths" type="xs:boolean">
<xs:annotation>
<xs:documentation>Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCompression" type="xs:boolean">
<xs:annotation>
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableCleanup" type="xs:boolean">
<xs:annotation>
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="DisableEventSubscription" type="xs:boolean">
<xs:annotation>
<xs:documentation>The attach method no longer subscribes to the `AppDomain.AssemblyResolve` (.NET 4.x) and `AssemblyLoadContext.Resolving` (.NET 6.0+) events.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
<xs:annotation>
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="ExcludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="IncludeRuntimeAssemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>Obsolete, use UnmanagedWinX86Assemblies instead</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UnmanagedWinX86Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged X86 (32 bit) assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>Obsolete, use UnmanagedWinX64Assemblies instead</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UnmanagedWinX64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged X64 (64 bit) assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UnmanagedWinArm64Assemblies" type="xs:string">
<xs:annotation>
<xs:documentation>A list of unmanaged Arm64 (64 bit) assembly names to include, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="PreloadOrder" type="xs:string">
<xs:annotation>
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="packages\Costura.Fody.6.0.0\build\Costura.Fody.props" Condition="Exists('packages\Costura.Fody.6.0.0\build\Costura.Fody.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,6 +13,8 @@
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -33,6 +36,9 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Costura, Version=6.0.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
<HintPath>packages\Costura.Fody.6.0.0\lib\netstandard2.0\Costura.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\WindowsAPICodePack-Core.1.1.2\lib\Microsoft.WindowsAPICodePack.dll</HintPath>
</Reference>
@@ -90,4 +96,14 @@
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\Fody.6.8.2\build\Fody.targets" Condition="Exists('packages\Fody.6.8.2\build\Fody.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Fody.6.8.2\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Fody.6.8.2\build\Fody.targets'))" />
<Error Condition="!Exists('packages\Costura.Fody.6.0.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.6.0.0\build\Costura.Fody.props'))" />
<Error Condition="!Exists('packages\Costura.Fody.6.0.0\build\Costura.Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Costura.Fody.6.0.0\build\Costura.Fody.targets'))" />
</Target>
<Import Project="packages\Costura.Fody.6.0.0\build\Costura.Fody.targets" Condition="Exists('packages\Costura.Fody.6.0.0\build\Costura.Fody.targets')" />
</Project>

244
README.md
View File

@@ -1 +1,243 @@
Create md5.json
# MD5Create
这是一个用C#开发的高效 **MD5文件校验工具**,能够遍历指定目录并生成完整的文件校验清单,支持**版本管理**和**文件去重存储**功能。
## 主要功能
### ✨ 核心特性
- **递归目录遍历**自动遍历指定目录及所有子目录生成完整的文件MD5清单
- **版本号管理**:支持为每次生成的清单添加版本号,便于增量更新和版本对比
- **文件去重存储**自动将所有文件复制到统一存储目录以MD5值命名相同内容只保留一份
- **异步并行处理**后台线程执行MD5计算界面实时显示进度支持大型目录处理
- **智能路径选择**:文件夹选择对话框支持直接输入路径,快速跳转到目标目录
- **长路径支持**完全支持Windows长路径>260字符突破传统路径限制
- **健壮性设计**:智能跳过无权限目录、符号链接,异常不中断,确保最大兼容性
### 📁 生成文件结构
```
目标目录/
├── MD5/
│ ├── md5.json # 主要输出文件JSON格式校验清单
│ └── File/ # 去重文件存储目录
│ ├── a1b2c3d4... # 以MD5值命名的文件无扩展名
│ ├── e5f6g7h8...
│ └── ...
```
### 📊 JSON输出格式
```json
{
"version": "1.0.0",
"data": {
"readme.txt": "c1a5298f939e87e8f962a5edfc206918",
"config.ini": "d85b1213473c2fd7c2045020a6b9c62b",
"assets": {
"logo.png": "1abcb33beeb811dca15f0ac3e47b88d9",
"styles": {
"main.css": "8f14e45fceea167a5a36dedd4bea2543"
}
}
}
}
```
### 🔒 安全特性
- **MD5碰撞检测**:文件复制前检查目标文件是否已存在,避免误覆盖
- **权限异常处理**:遇到无访问权限的目录/文件时自动跳过并记录日志
- **符号链接防护**:自动检测并跳过符号链接和联接点,避免无限递归
- **大小写兼容**使用不区分大小写的字典兼容Windows文件系统特性
## 运行要求
- **Windows 7** 或更高版本
- **.NET Framework 4.7.2** 或更高版本
- **磁盘空间**至少为源目录大小的2倍原文件 + 去重副本)
- **内存要求**:建议 **2GB 以上**(处理大型目录时)
## 技术架构
### 🔧 核心技术栈
- **.NET Framework 4.7.2 / C# 7.3**Windows Forms 桌面应用
- **异步文件处理**`async/await` + `Task.Run` 实现非阻塞UI
- **JSON序列化**`Newtonsoft.Json` 提供高性能JSON处理
- **现代文件选择**`Microsoft.WindowsAPICodePack` 支持地址栏输入
- **MD5算法**`System.Security.Cryptography.MD5` 标准实现
### 🛡️ 健壮性设计
- **异常隔离**:单个文件处理失败不影响整体流程
- **长路径支持**:通过 `App.config` 启用Windows长路径API
- **内存优化**大文件MD5计算使用流式处理避免内存溢出
- **进度反馈**:实时显示处理进度和详细日志,支持自动滚动
### 📈 性能指标
- **处理速度**:约 **50-100 MB/s**(取决于磁盘性能)
- **内存占用**< **100 MB**处理10,000文件以内
- **支持规模**:经测试支持 **100,000+** 文件的大型目录
- **UI响应**:异步处理保证界面始终响应,支持随时取消
### 日志示例
```
开始处理目录: D:\MyProject
创建MD5存储目录: D:\MyProject\MD5
创建文件存储目录: D:\MyProject\MD5\File
.\readme.txt
已复制: D:\MyProject\readme.txt -> D:\MyProject\MD5\File\c1a5298f939e87e8f962a5edfc206918
.\assets\logo.png
已复制: D:\MyProject\assets\logo.png -> D:\MyProject\MD5\File\1abcb33beeb811dca15f0ac3e47b88d9
md5.json文件已生成在D:\MyProject\MD5\md5.json
JSON内容MD5校验值f7d4c6e5b2a1c3e4d5f6a7b8c9d0e1f2
```
## 使用方法
### 🚀 快速开始
1. **选择目录**:点击 `...` 按钮选择要处理的目录
- 支持在地址栏直接粘贴路径快速跳转
- 支持网络路径和UNC路径
2. **设置版本**:在"版本"框中输入版本号(如 `1.0.0``v2.1-beta`
3. **开始处理**:点击"开始"按钮
4. **实时监控**:在执行窗口查看实时处理日志和进度
5. **完成确认**:处理完成后会显示输出文件位置和校验信息
### 💡 高级用法
- **增量更新**:通过对比不同版本的 `md5.json` 实现增量更新检测
- **文件去重**`MD5/File` 目录可作为去重文件库,节省存储空间
- **批量校验**生成的JSON文件可用于批量文件完整性校验
- **版本管理**结合Git等版本控制系统追踪文件变更历史
## 构建与部署
### 📦 构建要求
> 需要 **Visual Studio 2019 / 2022** 或更高版本
1. **克隆项目**
```bash
git clone <repository-url>
cd MD5Create
```
2. **安装依赖**
```powershell
# 通过NuGet包管理器自动恢复或手动安装
Install-Package Newtonsoft.Json -Version 13.0.3
Install-Package Microsoft.WindowsAPICodePack-Shell -Version 1.1.4
```
3. **编译项目**
- 选择 **Release | Any CPU** 配置
- 生成解决方案 (`Ctrl+Shift+B`)
4. **打包分发**
```
输出目录: bin/Release/
主程序: MD5Create.exe
依赖库: Newtonsoft.Json.dll, Microsoft.WindowsAPICodePack*.dll
配置: App.config
```
### 🔧 配置说明
#### App.config 重要配置
```xml
<runtime>
<!-- 启用长路径支持 (Windows 10 1607+) -->
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false" />
</runtime>
```
## 故障排除
### ❌ 常见问题
**问题1提示"未能找到 CommonOpenFileDialog"**
- **原因**:缺少 `Microsoft.WindowsAPICodePack-Shell` NuGet包
- **解决方案**通过NuGet包管理器安装该依赖包
**问题2处理大目录时程序卡死**
- **原因**文件数量过多导致UI阻塞
- **解决方案**:已使用异步处理,如仍卡顿请检查磁盘性能和可用内存
**问题3某些文件无法访问**
- **原因**:文件被占用、权限不足或系统保护
- **解决方案**:程序会自动跳过并记录日志,不影响其他文件处理
**问题4长路径文件处理失败**
- **检查**确认Windows版本支持长路径Win10 1607+
- **解决方案**启用系统长路径支持或升级到新版Windows
**问题5JSON文件过大**
- **原因**:目录包含大量文件
- **建议**:考虑分批处理或排除不必要的子目录
**问题6MD5计算速度慢**
- **检查**:磁盘性能、文件大小分布
- **优化**使用SSD、关闭实时防病毒扫描
## 依赖项
### 📚 NuGet 包
```xml
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
<package id="Microsoft.WindowsAPICodePack-Core" version="1.1.4" targetFramework="net472" />
<package id="Microsoft.WindowsAPICodePack-Shell" version="1.1.4" targetFramework="net472" />
```
### 🖥️ 系统要求
- **.NET Framework 4.7.2+**
- **Windows 7 SP1** 或更高版本
- **可选**Windows 10 1607+ (完整长路径支持)
## 项目结构
```
MD5Create/
├── Form1.cs # 主窗体逻辑
├── Form1.Designer.cs # 窗体设计器代码
├── Form1.resx # 窗体资源文件
├── Program.cs # 程序入口点
├── App.config # 应用程序配置
├── packages.config # NuGet包配置
├── MD5Create.csproj # 项目文件
├── MD5Create.sln # 解决方案文件
└── README.md # 项目文档
```
## 开发信息
- **开发语言**C# 7.3
- **UI框架**Windows Forms
- **架构模式**:事件驱动 + 异步处理
- **加密算法**MD5 (System.Security.Cryptography)
- **JSON处理**Newtonsoft.Json
## 更新日志
### v3.0 - 健壮性增强版本 (最新)
-**重大升级**:完整的异常处理和错误恢复机制
- ✅ 新增符号链接和联接点检测,防止无限递归
- ✅ 新增长路径支持突破260字符限制
- ✅ 重构为异步架构大幅提升UI响应性
- ✅ 新增文件去重机制避免MD5碰撞误覆盖
- ✅ 增强日志系统,支持实时滚动和详细错误信息
- ✅ 优化内存使用,支持超大目录处理
### v2.0 - 现代化UI版本
- ✅ 集成 Windows API Code Pack支持地址栏输入
- ✅ 新增版本号管理功能
- ✅ 新增文件复制和去重存储
- ✅ 改进JSON格式增加版本字段
- ✅ 优化界面布局,提升用户体验
### v1.0 - 基础版本
- 基础MD5计算和JSON生成功能
- 简单的目录遍历和文件处理
- Windows Forms基础界面
## 许可协议
本项目采用 **MIT License** 开源协议,允许自由使用、修改和分发。
---
**开发者**: OpenAI Assistant | **最后更新**: 2024-12 | **技术支持**: [GitHub Issues]

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Costura.Fody" version="6.0.0" targetFramework="net472" developmentDependency="true" />
<package id="Fody" version="6.8.2" targetFramework="net472" developmentDependency="true" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net472" />
<package id="WindowsAPICodePack-Core" version="1.1.2" targetFramework="net472" />
<package id="WindowsAPICodePack-Shell" version="1.1.1" targetFramework="net472" />