使用ilmerge实现.net程序静态链接
當編寫規模稍大一點的程序時,需要進行模塊劃分。我們一般是對每個模塊建一個工程,輸出一個類庫,這樣就形成了一個exe加多個類庫的解放方案。這樣本身是沒有什么問題的,就是發布上稍微有點麻煩,需要發布一個exe加多個dll文件。特別是那些需要經常更新的程序,其實本身可能并不大,一共也就幾百kb,但每次還要發布三四個dll確實令人厭煩,做成安裝包就更沒必要了。
在C++中,我們一般可以通過靜態鏈接解決這種問題,但在.net中卻不行,每個類庫只能輸出dll,VisualStudio官方也沒有提供靜態鏈接的選項,其實從理論上講要想合并似乎也不難,ildasm能夠把.NET程序反編譯成il,那么把兩個il合并到一個il當中再用il編譯就可以了。雖然M$卻沒有直接提供這種功能,但M$的一位大牛提供了一個工具ILMerge可以實現這種功能,可以在http://research.microsoft.com/~mbarnett/ILMerge.aspx下載。
網上也有一些文章對這個工具進行了介紹,margiex的blog中的說明就介紹的較簡明扼要,這里轉錄一下:
ilmerge /ndebug /target:exe /targetplatform:v1.1 /out:newclient.exe oldclient.exe /log AutoUpdater.dll DockingSuite.dll DocumentManager.dll FileHelpers.dll OutlookBar.dll SandBar.dll ICSharpCode.SharpZipLib.dll
解釋如下:
后面是主要的被合并的組件名稱, 及相關所有的其它DLL;
上面的示例只是合并為EXE, 也可以多個DLL合并成一個DLL使用, 各自的命名空間不會改變;
- 不能合并interop這種由COM轉換過來的DLL; (可以合并,但相關依賴的DLL必須也一起合并, 第一次合并的時候只有Excel.dll,總是報錯,以為是interop的緣故,后來才發現是沒有合并vbide.dll的緣故,復制到目錄再一起合并,一切OK.)
- 如果有資源DLL, 應該將要被合并的oldclient.exe先改為別的名稱,然后合并后的輸出命名為:oldclient.exe,因為資源文件名是:oldclient.resources.dll,而ILMERGE不能合并資源文件,否則在導出后將找不到此資源文件。(如果哪位知道如何合并資源文件,請指教,謝謝)
- 雖然合并后的EXE比較大,但在用戶那里只有一個EXE,這樣直觀的多,也容易升級維護.
原文地址:http://www.cnblogs.com/margiex/archive/2008/06/24/302329.html
具體的詳細使用文檔請參看它的說明文檔,還是很簡單的。
另外,也可以通過編程的方式來調用ILMerge的庫來實現簡化合并,這里轉錄一下CodeProject上的一篇文章Post build step static linking tool for C#, using ILMerge的代碼:
Codeusing?System;
using?System.Text;
using?System.Collections;
namespace?HTMerge
{
????class?Program
????{???
????????static?void?Main(string[]?args)
????????{
????????????try
????????????{
????????????????String?strDir?=?"";
????????????????if?(args.Length?!=?1)
????????????????{
????????????????????Console.WriteLine("Usage:?HTMerge?directoryName");
????????????????????return;
????????????????}
????????????????else
????????????????{
????????????????????strDir?=?args[0];
????????????????}
????????????????String[]?exeFiles?=?System.IO.Directory.GetFiles(strDir,?"*.exe");
????????????????String[]?dllFiles?=?System.IO.Directory.GetFiles(strDir,?"*.dll");
????????????????ArrayList?ar?=?new?ArrayList();
????????????????Boolean?bAdded?=?false;
????????????????//there?might?be?more?than?1?exe?file,?
????????????????//we?go?for?the?first?one?that?isn't?the?vshost?exe
????????????????foreach?(String?strExe?in?exeFiles)
????????????????{
????????????????????if?(!strExe.Contains("vshost"))
????????????????????{
????????????????????????ar.Add(strExe);
????????????????????????bAdded?=?true;
????????????????????????break;
????????????????????}
????????????????}
????????????????if?(!bAdded)
????????????????{
????????????????????Console.WriteLine("Error:?No?exe?could?be?found");
????????????????????//I?know?multiple?returns?are?bad�
????????????????????return;
????????????????}
????????????????bAdded?=?false;
????????????????foreach?(String?strDLL?in?dllFiles)
????????????????{
????????????????????ar.Add(strDLL);
????????????????????bAdded?=?true;
????????????????}
????????????????//no?point?merging?if?nothing?to?merge?with!
????????????????if?(!bAdded)
????????????????{
????????????????????Console.WriteLine("Error:?No?DLLs?could?be?found");
????????????????????//I?know?multiple?returns?are?bad�
????????????????????return;
????????????????}
????????????????//You?will?need?to?add?a?reference?to?ILMerge.exe?from?Microsoft
????????????????//See?http://research.microsoft.com/~mbarnett/ILMerge.aspx
????????????????ILMerging.ILMerge?myMerge?=?new?ILMerging.ILMerge();
????????????????String[]?files?=?(String[])ar.ToArray(typeof(string));
????????????????String?strTargetDir?=?strDir?+?"\\Merged";
????????????????try
????????????????{
????????????????????System.IO.Directory.CreateDirectory(strTargetDir);
????????????????}
????????????????catch
????????????????{
????????????????}
????????????????//Here?we?get?the?first?file?name?
????????????????//(which?was?the?.exe?file)?and?use?that
????????????????//?as?the?output
????????????????String?strOutputFile?=?System.IO.Path.GetFileName(files[0]);
????????????????myMerge.OutputFile?=?strTargetDir?+?"\\"?+?strOutputFile;
????????????????myMerge.SetInputAssemblies(files);
????????????????myMerge.Merge();
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????Console.WriteLine(String.Format("Error?:{0}",ex.Message));
????????????}
????????}
????}
}
另外,需要說明的是,這個工具目前支持的是.net 2.0,那些.net 3.0 3.5的程序由于是和.net2.0同一個clr,也可以使用(我試過的)。
總結
以上是生活随笔為你收集整理的使用ilmerge实现.net程序静态链接的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三招看穿ERP软件是否可行
- 下一篇: webwork 标签 基本用法 例子