將DLL包含到單一EXE檔案內

今天在實作一個Console模式的程式時,有引用到Newtonsoft.Json類別中的一些JSON方法,因此在進行建置發行時,遇到了一個很妙的問題。

通常,我們選擇使用Console Mode進行開發,大部份的原因都是因為懶惰,例如懶得畫UI介面,或者懶得安裝部署,反正EXE檔Copy過去,點兩下就可以運行並直接解決問題,這不是一個非常完美的狀態嗎?

去除使用者必須先安裝.NET Framework這個問題不談,當程式中參考到某些組件,這通常就代表這個組件必須跟著你寫的執行檔一起部署過去Client端了(通常會發生在第三方組件上)。以我這個例子來說,當你到Debug目錄或者是Release目錄下,你會發現「Newtonsoft.Json.dll」乖乖的跟你的EXE檔躺在一起,如果你天真到只有Copy單一個EXE檔給使用者,那你就準備討罵了。

因此,接下來的問題是,我們要怎麼把引用到的DLL包進去EXE中呢?

一、請到微軟官方下載「ILMerge」,下載後請安裝。

二、願意的話,您可以到環境變數中的Path變數,將下列的路徑加入:(小心視別您作業系統的版本)

C:\Program Files (x86)\Microsoft\ILMerge

三、進行DLL與EXE的合體:

Start > Run > Cmd

D:\YourWorkDirectory>iLMerge /target:exe /out:New.exe Old.exe Newtonsoft.Json.dll

P.S /target 參數有多種選擇,可以綁成單一DLL、ConsoleEXE、WindowEXE,請自己打 ILMerge 後按 Enter 看說明。

當然,ILMerage還有其它的功能,有興趣或經驗的使用者,不妨留言大家一起討論。

20150618 Update

今天在ILMerge一個Google.GData.*.dll的時候,發現一個詭異的問題,就是無論你怎麼確定產生出來的.exe檔已經可以正確執行了,但是經過ILMerg去處理過後,怎麼跑怎麼出問題,例如會出現「System.MissingMethodException」或「System.String.IsNullOrWhiteSpace」等問題。

經過研究後,可以強制ILMerge去讀取我們指定的Framework版本的DLL,這樣在組建成單一執行檔的時候,可以強制到某一區載入DLL。參數語法如下:(版本與路徑請自行調整)

/targetplatform:v4,"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.1"
DLL Binding Include Merge EXE