如何制作仅一个exe文件的简易小工具

当开发一个简易的WPF、WinForm小工具时,有时候会引入一些外部dll,当你想要把制作好的小工具分享给自己的小伙伴使用时,你会发现如果不把引用的dll文件一同分享给他的话是无法使用的。这对于一个简易的小工具来说,显然不够友好,那有没有其它方式可以将最终的程序合并成一个单一的exe文件呢?显然是有的!下面就来说一下如何进行配置。

当你配置完成后,再次生成项目,会神奇的发现生成目录下只剩一个exe文件了,此时你一定很想知道这其中的奥妙。原理见文末注解!!!

方案一(推荐)

1. 引入NuGet包Costura.Fody
2. 在项目中添加FodyWeavers.xml文件,内容格式如下,高级用法详见git项目 Costura
<Weavers>
  <Costura/>
</Weavers>

此时/bin/Debug目录下生成的exe已经可以脱离dll使用,如果想要自动删除这些文件,可以参考方案二中的<!--构建完成后-->配置
注: 引入Fody包后如果出现生成解决方案报错的问题,清理下解决方案重新生成即可(猜测Fody不同版本对VS版本有要求)

方案二

1. .csproj文件Project块中添加如下配置
<Project>
  <!--引用依赖解析后-->
  <Target Name="AfterResolveReferences">
    <ItemGroup>
      <EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'">
        <LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName>
      </EmbeddedResource>
    </ItemGroup>
  </Target>
  <!--构建完成后-->
  <Target Name="DeleteOtherFile" AfterTargets="AfterBuild">
    <ItemGroup>
      <OtherFiles Include="$(OutputPath)\*" Exclude="$(OutputPath)\$(AssemblyName).*;$(OutputPath)\*.json" />
    </ItemGroup>
    <Delete Files="@(OtherFiles)" />
  </Target>
</Project>
 2. Program.cs文件中注册如下事件
[STAThread]
static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly;
    // 其它代码
}

private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
{
    var executingAssembly = Assembly.GetExecutingAssembly();
    var assemblyName = new AssemblyName(args.Name);
    var path = assemblyName.Name + ".dll";
    if (assemblyName.CultureInfo.Equals(CultureInfo.InvariantCulture) == false) path = $@"{assemblyName.CultureInfo}\{path}";
    using (var stream = executingAssembly.GetManifestResourceStream(path))
    {
        if (stream == null) return null;
        var assemblyRawBytes = new byte[stream.Length];
        stream.Read(assemblyRawBytes, 0, assemblyRawBytes.Length);
        return Assembly.Load(assemblyRawBytes);
    }
}
原理:将依赖的引用打包进嵌入式资源EmbeddedResource中,在项目启动时再从资源文件中装载程序集到应用程序。
注:Project - AfterBuild只是顺带删除了一下已被放入到资源中的dll文件,此操作非必须!!!
分享到:
本文链接:https://blog.renzicu.com/2022/singlefile-exe/index.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 许可协议。转载请注明出处!
THE END
二维码
打赏
文章目录
关闭
目 录