2019独角兽企业重金招聘Python工程师标准>>> hot3.png

WPF程序将DLL嵌入到EXE的两种方法

这一篇可以看作是《Visual Studio 版本转换工具WPF版开源了》的续,关于《Visual Studio 版本转换工具WPF版开源了》可以参看地下地址(两篇是一样的):

  1. 开源中国 http://my.oschina.net/chinesedragon/blog/308336
  2. 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,这两个工具的下载和帮助地址如下:

  1. ILMerge http://www.microsoft.com/en-us/download/details.aspx?id=17630
  2. 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有很多参数,其中有几个比较重要:

  1. /target:目标,有library和Winexe两种选择,当将多个DLL整合成一个DLL时可以使用library,当要整合为EXE时,应该使用Winexe.
  2. /out:输出,最终生成文件的路径和名称.
  3. /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) -&gt; $(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还有很多用法,可以到项目文档学习。

参考资料

  1. Combining multiple assemblies into a single EXE for a WPF application
  2. DLL嵌入exe中
  3. LibZ项目

Nuget是个十分强大的工具,使用Nuget在很多时候可以使解决方法变得简单,给Nuget赞一个!
再做下广告,Visual Studio版本转换工具WPF版的代码托管地址是:http://git.oschina.net/shupengluo/VSConverter,欢迎交流。

最后,再小小地鄙视下微软,^_^

转载于:https://my.oschina.net/chinesedragon/blog/309223

WPF程序将DLL嵌入到EXE的两种方法相关推荐

  1. DLL中资源切换的两种方法

    DLL中资源切换的两种方法 方法1 AFX_MANAGE_STATE(AfxGetAppModuleState());                // MFC扩展dll 或 AFX_MANAGE_ ...

  2. win10计算机桌面快捷方式,Win10程序快捷方式添加到桌面上的两种方法

    在使用电脑的时候一般都是把程序快捷方式添加到电脑桌面上,因为打开电脑面对的就是桌面.在桌面打开程序也是最快的.那么在Win10系统中如何把应用程序 快捷方式 添加到桌面上呢?方法有两种,这里就为大家一 ...

  3. 从内存中加载并运行exe(两种方法)

    windows似乎只提供了一种启动进程的方法:即必须从一个可执行文件中加载并启动.      而下面这段代码就是提供一种可以直接从内存中启动一个exe的变通办法.      用途嘛,     也许可以 ...

  4. c#简单记事本应用程序的快捷方式_C#创建快捷方式的两种方法

    一:用WSH直接创建快捷方式: 1.首先要添加引用. 添加引用的方法非常简单,右击你的项目并选择添加引用, 选择 COM 选项卡并选择 Windows Script Host Object Model ...

  5. python文件打包成可执行文件exe的两种方法

    python 可以做网站应用,也可以做客户端应用.但是客户端应用需要运行 py 脚本,如果用户不懂 python 就是一件比较麻烦的事情.幸好 pyton 有第三方模块可以将脚本可以转成 exe 执行 ...

  6. java程序将汉字转成拼音的两种方法

    1.使用pinyin4j将汉字转成拼音,附件为pinyin4j的jar包 Java代码   import net.sourceforge.pinyin4j.PinyinHelper; import n ...

  7. 小程序底部弹窗css_微信小程序之animation底部弹窗动画(两种方法)

    简单分享一下常用的底部弹窗层或下拉框弹出层(代码需要修改)的内容弹窗的动画效果,这里分享的是点击按钮后底部弹窗的动画效果.第一种方式是动态设置显示区域的高度,第二种方法是动态设置显示区域的移动的位置( ...

  8. WPF制作带圆角的文本框的两种方法

    方法一 <Window.Resources> <ControlTemplate x:Key="FilletTextBox" TargetType="{x ...

  9. inno setup打包的安装包如何在卸载完程序后可以继续安装_这两个方法就够了!快速制作Python程序Windows安装包...

    点击关注州的先生 编程应用.实战教程,不容错过 /00/ 前言 我们使用Python可以编写很多提高工作和学习效率的小工具,在编写完之后,如果我们想将其分享给更多的人使用,那么最便捷的方法就是将其打包 ...

最新文章

  1. 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!
  2. 一些很实用且必用的小脚本代码:
  3. SpringBoot连接Mysql数据库遇到Unable to load authentication plugin ‘caching_sha2_password解决方案
  4. fatal error C1001的一个解决心得
  5. 07.30《jQuery》——1.1DOM对和jQuery对象的转化
  6. 使用xadmin覆盖Django的admin
  7. Leetcode 448. Find All Numbers Disappeared in an Array
  8. Ehcache整合spring配置
  9. Centos 配置eth0 提示Device does not seem to be present -- 转载
  10. 中鸣机器人轨迹C语言教程,康宁小学机器人社团
  11. 用户服务协议和隐私政策
  12. ANSYS Workbench 目标参数优化案例分析
  13. 网站必备之简繁切换功能实现
  14. 手机电源管理芯片一般在哪
  15. 一文搞懂 | Linux 同步管理(上)
  16. Rstudio永久修改当前工作路径
  17. [C++]判断齐次坐标系中三点是否共线(三个向量是否共面)
  18. ResNext架构解析:深度神经网络的聚合残差变换
  19. 8421码 5421码 2421码 余三码
  20. 【011】疫苗接种管理系统

热门文章

  1. linux制作成后台服务,把dotnetcore 控制台app设置成linux后台服务
  2. C++ 向上转型初步01
  3. 软件工程---4.需求工程
  4. 【汇编语言】清华大学学堂在线《汇编语言程序设计》课程学习笔记
  5. select函数(一)
  6. pthread_cancel、pthread_equal函数
  7. 从新手到Flutter架构师,一篇就够!吐血整理
  8. 给Android程序员的一些面试建议,附带学习经验
  9. echo(),print(),print_r(),var_dump()的区别
  10. git 版本控制(一)