# MergeTool **Repository Path**: kaiouyang-sn/merge-tool ## Basic Information - **Project Name**: MergeTool - **Description**: 提供了对ILMerge工具的C#封装,简化了合并DLL的操作流程。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-04-19 - **Last Updated**: 2025-04-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ILMerge DLL合并工具 ILMerge是一个将多个.NET程序集合并为单个程序集的工具。这个封装类提供了对ILMerge工具的C#封装,简化了合并DLL的操作流程。 ## 使用场景 - 减少应用程序部署的DLL数量 - 合并第三方库到主程序集中 - 简化应用程序分发 ## 注意事项 1. 需要预先安装ILMerge工具 2. 合并的DLL必须是相同.NET版本的 3. 强名称程序集需要特殊处理 4. 合并后可能增加程序集大小 5. 某些反射操作可能在合并后失效 ## 帮助类定义 ```csharp using System.Diagnostics; /// /// ILMerge合并DLL的帮助类 /// public static class ILMergeHelper { /// /// 执行ILMerge合并DLL /// /// ILMerge的路径 /// 输出DLL的路径 /// 要合并的DLLs路径 /// 额外的ILMerge选项 /// 超时时间(毫秒),默认5分钟 /// 合并结果对象 public static MergeResult MergeDll( string ilmergePath, string outputDllPath, string[] dllsToMerge, string[] additionalOptions = null, int timeoutMs = 300000) { if (string.IsNullOrWhiteSpace(ilmergePath)) throw new ArgumentNullException(nameof(ilmergePath)); if (string.IsNullOrWhiteSpace(outputDllPath)) throw new ArgumentNullException(nameof(outputDllPath)); if (dllsToMerge == null || dllsToMerge.Length == 0) throw new ArgumentException("至少需要指定一个要合并的DLL", nameof(dllsToMerge)); // 检查文件是否存在 if (!File.Exists(ilmergePath)) return MergeResult.Fail($"ILMerge工具不存在: {ilmergePath}"); var missingDlls = dllsToMerge.Where(dll => !File.Exists(dll)).ToList(); if (missingDlls.Count != 0) return MergeResult.Fail($"找不到要合并的DLL文件: {string.Join(", ", missingDlls)}"); // 确保输出目录存在 string? outputDir = Path.GetDirectoryName(outputDllPath); if (!string.IsNullOrWhiteSpace(outputDir) && !Directory.Exists(outputDir)) { try { Directory.CreateDirectory(outputDir); } catch (Exception ex) { return MergeResult.Fail($"无法创建输出目录: {outputDir}. 错误: {ex.Message}"); } } // 构建ILMerge的命令行参数 var arguments = new System.Text.StringBuilder(); arguments.Append("/ndebug /target:dll "); // 添加额外选项 if (additionalOptions != null) { foreach (var option in additionalOptions) { arguments.Append($"{option} "); } } arguments.Append($"/out:\"{outputDllPath}\" "); arguments.Append(string.Join(" ", dllsToMerge.Select(dll => $"\"{dll}\""))); // 创建新的进程启动信息 var startInfo = new ProcessStartInfo { FileName = ilmergePath, Arguments = arguments.ToString(), UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, WorkingDirectory = Path.GetDirectoryName(ilmergePath) ?? Environment.CurrentDirectory }; try { using var process = new Process { StartInfo = startInfo }; // 启动ILMerge进程 if (!process.Start()) return MergeResult.Fail("无法启动ILMerge进程"); // 异步读取输出和错误信息 var outputTask = process.StandardOutput.ReadToEndAsync(); var errorTask = process.StandardError.ReadToEndAsync(); // 等待进程完成或超时 if (!process.WaitForExit(timeoutMs)) { try { process.Kill(); } catch { /* 忽略杀死进程时的异常 */ } return MergeResult.Fail($"ILMerge操作超时(超过 {timeoutMs}ms)"); } // 确保读取完成 Task.WaitAll(outputTask, errorTask); string output = outputTask.Result; string error = errorTask.Result; // 检查进程退出代码以确定是否成功 if (process.ExitCode == 0) { return File.Exists(outputDllPath) ? MergeResult.Success2(output, error) : MergeResult.Fail("ILMerge报告成功但未生成输出文件", output, error); } return MergeResult.Fail($"ILMerge失败,退出代码: {process.ExitCode}", output, error); } catch (Exception ex) { return MergeResult.Fail($"执行ILMerge时发生异常: {ex.Message}"); } } } /// /// ILMerge操作结果 /// public class MergeResult { public bool Success { get; } public string Output { get; } public string Error { get; } public string Message { get; } private MergeResult(bool success, string message, string output, string error) { Success = success; Message = message; Output = output; Error = error; } public static MergeResult Success2(string output, string error) => new MergeResult(true, "合并成功", output, error); public static MergeResult Fail(string message, string output = null, string error = null) => new MergeResult(false, message, output, error); } ``` #### 调用示例 ```csharp using System.Reflection; string currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); Console.WriteLine($"当前目录: {currentDir}"); string ilmergePath = $@"{currentDir}\ILMerge\ILMerge.exe"; Console.WriteLine($"ILMerge路径: {ilmergePath}"); string parentDir = Directory.GetParent(currentDir)?.FullName; Console.WriteLine($"上一级目录: {parentDir}"); // 输出 DLL 路径(args[0] 是输出名称,如 "MewTool_Test") string outputDllPath = $@"{parentDir}\{args[0]}.dll"; Console.WriteLine($"输出DLL路径: {outputDllPath}"); // 动态获取所有要合并的 DLL(跳过 args[0],从 args[1] 开始) string[] dllsToMerge = args .Skip(1) // 跳过第一个参数(输出名称) .Select(dll => Path.Combine(parentDir, dll)) // 拼接完整路径 .ToArray(); Console.WriteLine("待合并的DLL列表:"); foreach (string dll in dllsToMerge) { Console.WriteLine($"- {dll}"); } // 调用合并方法 var result = ILMergeHelper.MergeDll(ilmergePath, outputDllPath, dllsToMerge); // 输出详细结果 Console.WriteLine($"成功: {result.Success}"); Console.WriteLine($"消息: {result.Message}"); Console.WriteLine($"输出: {result.Output}"); Console.WriteLine($"错误: {result.Error}"); ``` ## 基本用法 ```csharp // 基本合并示例 var result = ILMergeHelper.MergeDll( ilmergePath: @"C:\Tools\ILMerge.exe", outputDllPath: @"C:\Output\MergedAssembly.dll", dllsToMerge: new[] { @"C:\Project\MainAssembly.dll", @"C:\Libs\Dependency1.dll", @"C:\Libs\Dependency2.dll" }); if (!result.Success) { Console.WriteLine($"合并失败: {result.Message}"); Console.WriteLine($"错误输出: {result.Error}"); } else { Console.WriteLine("合并成功"); } ``` ## 配置参考 ### 合并方法 ```csharp // 动态合并多个DLL到单个输出文件 // 依赖:ILMerge.exe (需放在程序同级ILMerge目录下) public static MergeResult MergeDll( string ilmergePath, // ILMerge.exe完整路径 string outputDllPath, // 合并后的输出路径 params string[] dlls // 要合并的所有DLL路径 ) ``` ### 参数说明表 | 参数 | 类型 | 必需 | 说明 | | ---------- | -------- | ---- | ------------------------------------------------------ | | args[0] | string | 是 | 输出文件名(不含扩展名,如 "MewTool_Test") | | args[1..n] | string[] | 是 | 要合并的DLL文件名列表(不含路径,如 "A.dll", "B.dll") | ### 路径生成逻辑 ![image](E:\Console\MergeTool\assets\image-20250419111752-bovw162.png) 1. 自动路径计算: - ILMerge.exe 路径:{当前目录}\ILMerge\ILMerge.exe - 输出DLL路径:{上级目录}\{args[0]}.dll - 合并DLL路径:{上级目录}\{args[1..n]} 2. 示例目录结构: ``` /bin ├── YourApp.exe ├── ILMerge/ │ └── ILMerge.exe └── Merged/ ├── A.dll ├── B.dll └── Output.dll # 合并结果 ``` ## 在项目中使用 ### 1. MergeTool.exe 复制 MergeTool 程序到项目根目录 ![image](E:\Console\MergeTool\assets\image-20250419112320-l1ie7tq.png) ### 2. 在VS构建事件后 ```csharp "$(TargetDir)MergeTool\MergeTool.exe" "MewTool_Test" "merge\MySql.Data.dll" "merge\RestSharp.dll" "MewTool.dll" ``` ### 3. 返回结果 | 字段 | 类型 | 说明 | | ------- | ------ | ------------------------------- | | Success | bool | 是否合并成功 | | Message | string | 简短的执行状态描述 | | Output | string | ILMerge工具的标准输出 | | Error | string | 错误信息(Success=false时有效) | ![image](E:\Console\MergeTool\assets\image-20250419112751-ixc2wr6.png)