WPF程序将DLL嵌入到EXE的两种方法
2019独角兽企业重金招聘Python工程师标准>>>
WPF程序将DLL嵌入到EXE的两种方法
这一篇可以看作是《Visual Studio 版本转换工具WPF版开源了》的续,关于《Visual Studio 版本转换工具WPF版开源了》可以参看地下地址(两篇是一样的):
- 开源中国 http://my.oschina.net/chinesedragon/blog/308336
- CNBLOGS http://www.cnblogs.com/luoshupeng/p/3946635.html
引言
前几一写了一个小工具————《Visual Studio版本转换工具》,由于使用了WPF做为界面,因此这个小程序运行必须附带两个DLL:Microsoft.Expression.Interactions.dll和System.Windows.Interactivity.dll,同时由于自己也写了一个库,一个小程序需要附带3个DLL,这种体验真的很不爽,于是就着手把DLL嵌入到EXE中去。
挫折
对于C#程序,要把DLL嵌入到EXE中去,最权威和最常见的方法就是使用ILMerge这个工具,这是个命令行工具,有很多参数,可以将DLL很完美的嵌入到EXE中去,如果嫌命令行麻烦,也有人开源开发了图形界面ILMergeGUI,这两个工具的下载和帮助地址如下:
- ILMerge http://www.microsoft.com/en-us/download/details.aspx?id=17630
- ILMerge-GUI http://ilmergegui.codeplex.com/
于是下载了这两个工具,却出现将DLL嵌入到EXE中错误的情况,在网上查了下原因,竟然是ILMerge不支持WPF程序,我勒了个去,微软,你让我说你什么好呢?
ILMerge可以将Winform程序的DLL完美地嵌入到EXE中去(这一点我亲自测试了下,很不,点赞),但对WPF却不支持,原因是WPF的DLL中含有资源无法解决,微软,你好意思说这个工具是你开发的吗?
Winform程序将DLL嵌入到EXE中(一)——使用命令行 ##
下载ILMerge或者同时下载ILMerge-GUI,使用图形界面和使用命令行是同一个道理,只是图形界面简单些,所以这里以命令行说明。
我是下载ILMerge安装后,把ILMerge.exe复制到C:\Windows目录下去了,这样可以直接在命令行中使用而不用去设置环境变量,不管怎样,只要能够在命令行下使用这个工具就行。
ILMerge有很多参数,其中有几个比较重要:
- /target:目标,有library和Winexe两种选择,当将多个DLL整合成一个DLL时可以使用library,当要整合为EXE时,应该使用Winexe.
- /out:输出,最终生成文件的路径和名称.
- /log:输入,如果输入是EXE时可以不使用此参数直接写,而如果输入时DLL时,最好使用此参数
还有其它一些参数,使用时可以百度或者google一下,这是我测试的一张图片:
Winform程序将DLL嵌入到EXE中(二)——使用ILMerge.MSBuild.Tasks
ILMerge也使用Nuget发布了工具,使用Nuget的好处想必大家都知道,所以推荐使用这种方法。
第一步, 使用Nuget图形或Nuget命令下载ILMerge.MSBuild.Tasks
PM> Install-Package ILMerge.MSBuild.Tasks
第二步, 把VS项目文件记事本或者其它文本编辑工具打开,我使用的是Sublime Text 3,并按照如下格式根据实际情况修改:
<!-- Code to merge the assemblies into one:setup.exe -->
<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)LIB1_To_MERGE.dll" /> <!-- 这儿改成需要做嵌入的dll名 --><MergeAsm Include="$(OutputPath)LIB2_To_MERGE.dll" /></ItemGroup><PropertyGroup><MergedAssembly>$(ProjectDir)$(OutDir)MERGED_ASSEMBLY_NAME.exe</MergedAssembly><!-- 这儿改成需要做输出的exe名 --></PropertyGroup><Message Text="ILMerge @(MergeAsm) -> $(MergedAssembly)" Importance="high" /><ILMerge InputAssemblies="@(MergeAsm)" OutputFile="$(MergedAssembly)" TargetKind="SameAsPrimaryAssembly" />
</Target>
这样编译后就可以了。
WPF程序将DLL嵌入到EXE中(一)——将DLL自动转换为嵌入资源
第一步,修改项目文件,将DLL自动转换为嵌入资源。
把VS项目文件记事本或者其它文本编辑工具打开,我使用的是Sublime Text 3,并将下面内容添加到文件末尾:
<Target Name="AfterResolveReferences"><ItemGroup><EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"><LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName></EmbeddedResource></ItemGroup>
</Target>
第二步,修改App.xaml文件,在程序启动时加载资源
public partial class App : Application
{private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args){Assembly executingAssembly = Assembly.GetExecutingAssembly();var executingAssemblyName = executingAssembly.GetName();var resName = executingAssemblyName.Name + ".resources";AssemblyName assemblyName = new AssemblyName(args.Name); string path = "";if (resName == assemblyName.Name){path = executingAssemblyName.Name + ".g.resources"; ;}else{path = assemblyName.Name + ".dll";if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false){path = String.Format(@"{0}\{1}", assemblyName.CultureInfo, path);}}using (Stream stream = executingAssembly.GetManifestResourceStream(path)){if (stream == null)return null;byte[] assemblyRawBytes = new byte[stream.Length];stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);return Assembly.Load(assemblyRawBytes);}}protected override void OnStartup(StartupEventArgs e){base.OnStartup(e);AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;}
}
第三步,dll嵌入exe后,目录中的dll就没用了,配置Post buid 脚本自动删除dll:
cd $(TargetDir)
del *.dll
有些情况下,以上方法也不行,那么可以尝试 Eazfuscator.NET Eazfuscator.NET以前免费,现在已经变成收费软件了,不过找个免费的3.3版本也可以支持VS2010和VS2012
WPF程序将DLL嵌入到EXE中(二)——使用LibZ Container
LibZ是ILMerge的另外一个选择,它同样可以把DLL嵌入到EXE中去,在我的测试中它可以完成WPF程序的DLL嵌入到EXE中去,但好像这个组件使用的人不是很多。 LibZ Container的项目主页是http://libz.codeplex.com/
LibZ同样提供了Nuget下载,使用Nuget有很多好处,所以推荐使用这种方式。
使用Nuget图形或者命令下载LibZ.Bootstrap
Install-Package LibZ.Bootstrap
然后,配置Post buid 脚本:
set LIBZ=$(SolutionDir)packages\LibZ.Bootstrap.1.1.0.2\tools\libz.exe
%LIBZ% inject-dll --assembly VSConverter.WPF.exe --include *.dll --move
编译通过后就可以了。这里需要注意的是--assembly后的参数是项目生成的文件名. LibZ还有很多用法,可以到项目文档学习。
参考资料
- Combining multiple assemblies into a single EXE for a WPF application
- DLL嵌入exe中
- LibZ项目
Nuget是个十分强大的工具,使用Nuget在很多时候可以使解决方法变得简单,给Nuget赞一个!
再做下广告,Visual Studio版本转换工具WPF版的代码托管地址是:http://git.oschina.net/shupengluo/VSConverter,欢迎交流。
最后,再小小地鄙视下微软,^_^
转载于:https://my.oschina.net/chinesedragon/blog/309223
WPF程序将DLL嵌入到EXE的两种方法相关推荐
- DLL中资源切换的两种方法
DLL中资源切换的两种方法 方法1 AFX_MANAGE_STATE(AfxGetAppModuleState()); // MFC扩展dll 或 AFX_MANAGE_ ...
- win10计算机桌面快捷方式,Win10程序快捷方式添加到桌面上的两种方法
在使用电脑的时候一般都是把程序快捷方式添加到电脑桌面上,因为打开电脑面对的就是桌面.在桌面打开程序也是最快的.那么在Win10系统中如何把应用程序 快捷方式 添加到桌面上呢?方法有两种,这里就为大家一 ...
- 从内存中加载并运行exe(两种方法)
windows似乎只提供了一种启动进程的方法:即必须从一个可执行文件中加载并启动. 而下面这段代码就是提供一种可以直接从内存中启动一个exe的变通办法. 用途嘛, 也许可以 ...
- c#简单记事本应用程序的快捷方式_C#创建快捷方式的两种方法
一:用WSH直接创建快捷方式: 1.首先要添加引用. 添加引用的方法非常简单,右击你的项目并选择添加引用, 选择 COM 选项卡并选择 Windows Script Host Object Model ...
- python文件打包成可执行文件exe的两种方法
python 可以做网站应用,也可以做客户端应用.但是客户端应用需要运行 py 脚本,如果用户不懂 python 就是一件比较麻烦的事情.幸好 pyton 有第三方模块可以将脚本可以转成 exe 执行 ...
- java程序将汉字转成拼音的两种方法
1.使用pinyin4j将汉字转成拼音,附件为pinyin4j的jar包 Java代码 import net.sourceforge.pinyin4j.PinyinHelper; import n ...
- 小程序底部弹窗css_微信小程序之animation底部弹窗动画(两种方法)
简单分享一下常用的底部弹窗层或下拉框弹出层(代码需要修改)的内容弹窗的动画效果,这里分享的是点击按钮后底部弹窗的动画效果.第一种方式是动态设置显示区域的高度,第二种方法是动态设置显示区域的移动的位置( ...
- WPF制作带圆角的文本框的两种方法
方法一 <Window.Resources> <ControlTemplate x:Key="FilletTextBox" TargetType="{x ...
- inno setup打包的安装包如何在卸载完程序后可以继续安装_这两个方法就够了!快速制作Python程序Windows安装包...
点击关注州的先生 编程应用.实战教程,不容错过 /00/ 前言 我们使用Python可以编写很多提高工作和学习效率的小工具,在编写完之后,如果我们想将其分享给更多的人使用,那么最便捷的方法就是将其打包 ...
最新文章
- 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!
- 一些很实用且必用的小脚本代码:
- SpringBoot连接Mysql数据库遇到Unable to load authentication plugin ‘caching_sha2_password解决方案
- fatal error C1001的一个解决心得
- 07.30《jQuery》——1.1DOM对和jQuery对象的转化
- 使用xadmin覆盖Django的admin
- Leetcode 448. Find All Numbers Disappeared in an Array
- Ehcache整合spring配置
- Centos 配置eth0 提示Device does not seem to be present -- 转载
- 中鸣机器人轨迹C语言教程,康宁小学机器人社团
- 用户服务协议和隐私政策
- ANSYS Workbench 目标参数优化案例分析
- 网站必备之简繁切换功能实现
- 手机电源管理芯片一般在哪
- 一文搞懂 | Linux 同步管理(上)
- Rstudio永久修改当前工作路径
- [C++]判断齐次坐标系中三点是否共线(三个向量是否共面)
- ResNext架构解析:深度神经网络的聚合残差变换
- 8421码 5421码 2421码 余三码
- 【011】疫苗接种管理系统
热门文章
- linux制作成后台服务,把dotnetcore 控制台app设置成linux后台服务
- C++ 向上转型初步01
- 软件工程---4.需求工程
- 【汇编语言】清华大学学堂在线《汇编语言程序设计》课程学习笔记
- select函数(一)
- pthread_cancel、pthread_equal函数
- 从新手到Flutter架构师,一篇就够!吐血整理
- 给Android程序员的一些面试建议,附带学习经验
- echo(),print(),print_r(),var_dump()的区别
- git 版本控制(一)