ILMerge là gì? Cách merge các DLLs lại làm một hay làm sao để merge các DLLs vào một file .EXE bất kỳ? Đó hẳn là giải pháp tốt cho các ứng dụng Stand–alone. Vậy ta sẽ làm như thế nào?
Như bài viết trước tôi đã đề cập về IL hay MSIL, các bạn có thể xem lại tại đây để hiểu thêm về chúng.
Tôi nghĩ sẽ có lúc các bạn cũng sẽ như tôi – đi tìm một giải pháp để tạo ra một ứng dụng “độc lập”, gọn và dễ dàng cho việc deploy. Và hôm nay tôi sẽ chia sẻ giải pháp mà tôi tìm được.
Như các bạn đã biết, tất cả các tập tin dạng DLL hay EXE nguyên bản trên nền tảng .NET đều là các tập tin chứa mã nguồn MSIL. Đó là lý do quan trọng tôi chọn giải pháp sau đây để merge các Dlls thành một – vì chúng cùng chung bản chất.
Một tool khá mạnh mẽ đó là ILMerge và nhẹ. Nó là tool chính chủ Microsoft (dạng Console). Ngoài ra chúng ta còn được hỗ trợ ILMerge-GUI – sẽ dễ sử dụng hơn nguyên bản là console.
Giao diện khá thân thiện với ILMerge-GUI
Có vẻ như chuyên nghiệp hơn với ILMerge-Console
Nhưng không lẽ cứ mỗi lần muốn Merge DLL hay EXE chúng ta lại phải mở ILMErge-GUI hay Console để merge sao? Tôi thấy có những cách ít tốn công hơn như sau:
- Viết một Batch script dạng file *.bat hay *.cmd gì đó. Chúng ta chỉ việc Double-Click file này để thực thi ILMerge-Console.
- Cùng ý tưởng trên, ta viết Powershell script thay về Batch script.
- Gọn hơn nữa ta sẽ config sao cho khi build project của mình xong, MSBuild sẽ tự gọi một trong 2 script trên. Ta sẽ config ở Post build event của project. Chọn project -> Chuột phải -> Property -> Build event -> Post build event.
- Cách cuối là tạo một build target. Mỗi khi ta build success thì ILMerge sẽ merge các file ta chỉ định và xuất ra file cuối cùng.
Tôi thấy cách 4 là hay nhất nên tôi sẽ hướng dẫn cách này.
Giả sử tôi có một solution gồm 2 project là DataUtilities và DataConsoleCollector. Trong đó DataConsoleCollector là một console project và DataUtilities là library project. Project DataConsoleCollector add reference project DataUtilities.
Kết quả mong đợi sau khi build xong của tôi là chỉ có file DataConsoleCollector.EXE được tạo ra mà thôi. Để làm được tôi tiến hành install lần lượt 2 Nuget sau.
Install-Package ilmerge // version="2.14.1208" Install-Package ILMerge.MSBuild.Tasks // version="1.0.0.3"
Tiếp theo ta sẽ add build target vào file DataConsoleCollector.csproj
Chú ý là trước khi bạn thêm target này vào, hãy kéo xuống cuối file, bạn sẽ thấy dòng sau.
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
Tiếp theo ta sẽ thêm target mới vào ngay sau dòng trên. Sau đây là kết quả cuối cùng:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <UsingTask TaskName="ILMerge.MSBuild.Tasks.ILMerge" AssemblyFile="$(SolutionDir)\packages\ILMerge.MSBuild.Tasks.1.0.0.3\tools\ILMerge.MSBuild.Tasks.dll" /> <Target Name="AfterBuild"> <ItemGroup> <MergeAsm Include="$(OutputPath)$(TargetFileName)" /> <MergeAsm Include="$(OutputPath)DataUtilities.dll" /> </ItemGroup> <PropertyGroup> <MergedAssembly>$(OutputPath)\DataConsoleCollector.Merged.exe</MergedAssembly> </PropertyGroup> <Message Text="OutputFile: $(OutputDir)\DataConsoleCollector.Merged.exe" Importance="high" /> <Message Text="ILMerge @(MergeAsm) -> $(MergedAssembly)" Importance="high" /> <ILMerge InputAssemblies="@(MergeAsm)" OutputFile="$(MergedAssembly)" TargetKind="SameAsPrimaryAssembly" /> </Target>
Đôi khi bạn sẽ gặp lỗi khi merge các DLLs, bạn có thể thêm hai thông tin sau (LogFile và ShouldLog) để có thể có file log của ILMerge.
<ILMerge InputAssemblies="@(MergeAsm)" OutputFile="$(MergedAssembly)" TargetKind="SameAsPrimaryAssembly" LogFile="D:\ILMerge.log" ShouldLog="True"/>
Chú thích: dưới đây là phần config cho các DLL/EXE mà bạn muốn merge lại với nhau.Trong đó TargetFileName chính là file gốc DataConsoleCollector.exe
<ItemGroup> <MergeAsm Include="$(OutputPath)$(TargetFileName)" /> <MergeAsm Include="$(OutputPath)DataUtilities.dll" /> </ItemGroup>
Còn đây là phần config cho file DLL/EXE mà bạn muốn xuất ra.
<PropertyGroup> <MergedAssembly>$(OutputPath)\DataConsoleCollector.Merged.exe</MergedAssembly> </PropertyGroup>
Thế là xong phần config. Vậy là bạn chỉ cần nhấn build là bạn sẽ nhận được kết quả như mong đợi. Nhưng nếu bạn nhận được lỗi thì hãy lưu ý rằng với đường dẫn output bạn config là “$(OutputPath)\Merged.exe” và OutputPath = “…\bin\debug” thì tập tin output sẽ ở “…\bin\debug\Merged.exe“. Vì ILMerge không tự tạo folder nên bạn hãy tạo đến folder debug rồi thử build lại.
Xin nhắc lại rằng ILMerge chỉ merge được các file là MSIL. Đôi khi bạn sẽ không nhận được bất kỳ thông báo lỗi nào cho việc merge native code nhưng bạn cũng sẽ không nhận được kết quả như mong đợi ví dụ như merge log4net.dll.
ILMerge không thể dùng cho ứng dụng WPF. Xem cách khác tại đậy
Tải về source code sau đây để thử nghiệm. Nhớ rebuild solution để tải nuget về vì tôi đã xóa chúng cho nhẹ file.
Have you ever thought about writing an ebook or guest authoring on other blogs? I have a blog based upon on the same ideas you discuss and would love to have you share some stories/information. I know my readers would enjoy your work. If you are even remotely interested, feel free to shoot me an email.
Giờ có cái này nè, tiện hơn nhiều. Add từ nuget rồi là nó tự cấu hình xuất ra chung với folder debug luôn.
https://github.com/emerbrito/ILMerge-MSBuild-Task
Cảm ơn bạn.