Visual Studio編譯小技巧:工具程式一檔搞定

我經常寫小工具程式,不用安裝程式,單一EXE檔隨Copy隨用是最理想的部署設計。不過,程式稍稍複雜就難免依功能屬性拆分多個專案,有時需用到跨專案的共享程式庫,至於引用Json.NET、Dapper、NLog等必備套件的情況更是普遍。例如以下專案,Tool為Console Application(EXE)專案,引用Model類別程式庫專案,還參考了Json.NET:

編譯後會產生三組組件檔:Tool.exe、Model.dll與Newtonsoft.Json.dll,得一起部署到客戶端才能正確執行。

要實現單一EXE檔搞定,.NET有個好用工具-ILMerge,可將多個DLL、EXE檔合併成單一檔案(ILMerge使用方式可參考保哥的介紹文),原本想花點時間研究怎麼安排AfterPost事件執行ILMerge,驚喜地發現已有好心人包成MSBuild的Task!

在NuGet使用msbuild.ilmerge查詢,可以找到MSBuild.ILMerge.Task,二話不說,安裝到專案。

安裝後專案會多出ILMerge.props、ILMergeOrder.txt,但大部分情況下不需修改,直接編譯就好。

重新編譯可發現Model.dll及Newtonsoft.Json.dll不見了,只剩一個變胖的Tool.exe,使用時只需Copy這個檔案就行了。

用JustDecompile解析,可以看到Tool.exe裡藏了Model跟Newtonsoft.Json組件裡的所有型別。

用這種做法即可輕鬆一檔搞定小工具程式的部署,非常方便。

補充:MSBuild.ILMerge.Task預設會將參照到的DLL都包進EXE檔,如果想略過特定DLL,可將DLL的Copy Local屬性設為False即可排除。

歡迎推文分享:
Published 06 April 2016 10:12 PM 由 Jeffrey
Filed under:
Views: 40,603



意見

# Peter said on 16 May, 2016 05:01 AM

你好,黑大

最近我用這個套件,發生一個詭異的問題。

就是我專案有個套件,相依於

System.Net.Http.Formatting.dll

System.Web.Http.dll

(以上兩個都是裝套件產生的)

導致該套件合併失敗..這有解嗎?!

# Jeffrey said on 16 May, 2016 05:10 AM

to Peter, 這兩個System.* DLL來自NuGet packages目錄還是GAC?合併錯誤時有錯誤訊息嗎?

# Peter said on 16 May, 2016 06:25 AM

黑大,你好

我是安裝 Manatee.Trello.WebApi 這是用來處理 Trello 相關的套件中的一個。

我後來發現他會順便安裝

Microsoft.AspNet.WebApi.Client.5.2.3 (System.Net.Http.Formatting.dll)

Microsoft.AspNet.WebApi.Core.5.2.3

(System.Web.Http.dll)

的兩個套件

他會出現這樣的錯誤

ILMerge.Merge: ERROR!!: Duplicate type 'System.Net.Http.HttpRequestMessageExtensions' found in assembly 'System.Web.Http'. Do you want to use the /alllowDup option?

# Jeffrey said on 17 May, 2016 10:09 AM

to Peter, 請參考我的最新研究報告:blog2.darkthread.net/post-2016-05-17-msbuild-ilmerge-task-dup-type.aspx

# livezingy said on 15 July, 2016 11:33 PM

黑大,您好

我安装了MSBuild.ILMerge.Task,选择“重新生成”是可以成功的;但是在debug或者release模式下,选择“启动”时会报错:尝试运行项目时出错:未能加载文件或程序集或它的某一个依赖项。生成此程序集的运行比当前加载的运行时新,无法加载此程序集。

请问呢这是正常现象吗?原因是什么呢?谢谢解答 :)

# Jeffrey said on 18 July, 2016 08:55 AM

to livezingy,我自己的測試未遇過你說的狀況,加上資訊有限,不太能推斷問題所在。建議你另開一個形態類似但極度簡化的專案加上MSBuild.ILMerge.Task,看是否也會遇到相同問題,接著再逐步加入細節調整成會出錯的案例,看在哪一階段出現錯誤有助於找出原因。

# agrozyme said on 02 December, 2016 04:08 PM

黑大,您好,我試著安裝 MSBuild.ILMerge.Task,並建立一個空的 WPF 程式,在重建專案時發生這個錯誤訊息,請問該如何排除?

MSB4096 The item "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.CSharp.dll" in item list "ReferencePath" does not define a value for metadata "CopyLocal".  In order to use this metadata, either qualify it by specifying %(ReferencePath.CopyLocal), or ensure that all items in this list define a value for this metadata. D:\Code\TestDll\cn5ueahs.tmp_proj D:\Code\TestDll\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets 35

# agrozyme said on 03 December, 2016 10:28 AM

找到解法了~

wefollownews.appspot.com/.../1528.html

# Jeffrey said on 04 December, 2016 07:48 PM

to agrozyme, 謝謝分享(已筆記)

# Jake said on 02 February, 2017 04:13 AM

大大你好

就像你一樣我有成功將dll merge起來(A+B+C)

A為主要組件

但我另一個專案參考了這個merged dll

為何無法使用裡面次要組件(B)的類別呢?

# Jake said on 02 February, 2017 04:35 AM

補充上面所述

我要使用B dll 裡面的類別 X

若我using B

編譯器會說 X存在於兩個dll(A跟B)

若我不using

會說找不到類型

# Jeffrey said on 03 February, 2017 06:41 AM

to Jake, 能提供一個重現問題的小專案嗎?

# michael said on 01 February, 2018 04:41 AM

黑大,您好

請問我在NuGet登錄使用msbuild.ilmerge查詢,可以找到MSBuild.ILMerge.Task ,但是下載不下來

他的下載按鈕只顯示 copied 是還需要哪些條件嗎?

# michael said on 01 February, 2018 04:42 AM

黑大,您好

請問我在NuGet登錄使用msbuild.ilmerge查詢,可以找到MSBuild.ILMerge.Task ,但是下載不下來

他的下載按鈕只顯示 copied 是還需要哪些條件嗎?

# Jeffrey said on 01 February, 2018 10:52 AM

to michael, 沒看過類似狀況,可以貼張圖嗎?

# michael said on 02 February, 2018 02:19 AM

如何張貼圖?

# Jeffrey said on 02 February, 2018 02:50 AM

to michael, 如果沒有慣用的分享來源,可以用 https://imgur.com/

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<April 2016>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication