是否可以将一个预先存在的DLL嵌入到一个编译好的c#可执行文件中(这样你就只有一个文件可以分发)?如果这是可能的,人们会怎么去做呢?

通常情况下,我不介意把dll放在外面,让安装程序处理所有事情,但工作中有几个人问过我这个问题,老实说,我不知道。


当前回答

在上面扩展@Bobby的回答。您可以编辑.csproj,以便在构建时使用IL-Repack自动将所有文件打包到单个程序集中。

使用Install- package ILRepack.MSBuild.Task安装nuget ILRepack.MSBuild.Task包 编辑.csproj的AfterBuild部分

下面是一个简单的示例,它将ExampleAssemblyToMerge.dll合并到项目输出中。

<!-- ILRepack -->
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

   <ItemGroup>
    <InputAssemblies Include="$(OutputPath)\$(AssemblyName).exe" />
    <InputAssemblies Include="$(OutputPath)\ExampleAssemblyToMerge.dll" />
   </ItemGroup>

   <ILRepack 
    Parallel="true"
    Internalize="true"
    InputAssemblies="@(InputAssemblies)"
    TargetKind="Exe"
    OutputFile="$(OutputPath)\$(AssemblyName).exe"
   />
</Target>

其他回答

如果它们实际上是托管程序集,您可以使用ILMerge。对于本地dll,您将有更多的工作要做。

请参见:如何将c++ windows dll合并到c#应用程序exe中?

这听起来可能很简单,但WinRar提供了将一堆文件压缩为自提取可执行文件的选项。 它有很多可配置的选项:最终图标,提取文件到给定的路径,提取后执行的文件,自定义logo/文本在提取期间显示的弹出窗口,根本没有弹出窗口,许可协议文本,等等。 在某些情况下可能有用。

您可以将dll作为嵌入式资源添加,然后让程序在启动时将它们解压缩到应用程序目录中(在检查它们是否已经存在之后)。

虽然制作安装文件非常容易,但我认为这样做并不值得。

编辑:这种技术对于. net程序集来说很容易。与非。NET dll,这将是更多的工作(你必须弄清楚在哪里解包文件和注册它们等等)。

是的,可以将. net可执行文件与库合并。有多种可用的工具来完成这项工作:

ILMerge是一个实用程序,可用于将多个. net程序集合并为单个程序集。 Mono mkbundle,将libmono的exe和所有程序集打包到一个二进制包中。 IL-Repack是ILMerge的FLOSS替代品,具有一些附加特性。

此外,这可以与Mono链接器结合使用,它可以删除未使用的代码,从而使生成的程序集更小。

另一种可能是使用。net z,它不仅允许压缩程序集,还可以将dll直接打包到exe中。与上面提到的解决方案的不同之处在于,.NETZ不会合并它们,它们是单独的程序集,但被打包到一个包中。

. netz是一个开源工具,它压缩和打包Microsoft . net Framework可执行文件(EXE, DLL),以使它们更小。

在上面扩展@Bobby的回答。您可以编辑.csproj,以便在构建时使用IL-Repack自动将所有文件打包到单个程序集中。

使用Install- package ILRepack.MSBuild.Task安装nuget ILRepack.MSBuild.Task包 编辑.csproj的AfterBuild部分

下面是一个简单的示例,它将ExampleAssemblyToMerge.dll合并到项目输出中。

<!-- ILRepack -->
<Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

   <ItemGroup>
    <InputAssemblies Include="$(OutputPath)\$(AssemblyName).exe" />
    <InputAssemblies Include="$(OutputPath)\ExampleAssemblyToMerge.dll" />
   </ItemGroup>

   <ILRepack 
    Parallel="true"
    Internalize="true"
    InputAssemblies="@(InputAssemblies)"
    TargetKind="Exe"
    OutputFile="$(OutputPath)\$(AssemblyName).exe"
   />
</Target>