# 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") |
### 路径生成逻辑

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 程序到项目根目录

### 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时有效) |
