如何将附属程序集嵌入到 EXE 文件中

发布于 2024-08-06 04:21:40 字数 102 浏览 6 评论 0原文

我遇到的问题是,我需要将 C# 项目作为单个 EXE 文件分发,该文件不是安装程序,而是真正的程序。它还需要包含当前位于子目录中的翻译。

是否可以将其直接嵌入到二进制文件中?

I got the problem that I need to distribute a C# project as a single EXE file which is not an installer but the real program. It also needs to include a translation which currently resides in a subdirectory.

Is it possible to embed it directly into the binary?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

撑一把青伞 2024-08-13 04:21:40

简短的答案是肯定的,有一个名为 汇编链接器 (AL.exe)< /a> 将以这种方式嵌入程序集。它的主要用例是本地化,听起来这也是您所需要的。如果是这样,那应该很简单。

例如:

al /t:lib /embed:strings.de.resources /culture:de /out:MyApp.resources.dll

al.exe /culture:en-US /out:bin\Debug\en-US\HelloWorld.resources.dll /embed:Resources\MyResources.en-US.resources,HelloWorld.Resources.MyResources.en-US .resources /template:bin\Debug\HelloWorld.exe

这个 是 MSDN 的示例演练,其中包含上述示例以及更多内容。您还可能需要阅读这篇博文,其中解释了其用法再远一点。

The short answer is yes, there is a program called Assembly Linker (AL.exe) that will embed assemblies in this way. Its main use case is localization, sounds like that is what you need it for too. If so, it should be straightforward.

Eg:

al /t:lib /embed:strings.de.resources /culture:de /out:MyApp.resources.dll

or

al.exe /culture:en-US /out:bin\Debug\en-US\HelloWorld.resources.dll /embed:Resources\MyResources.en-US.resources,HelloWorld.Resources.MyResources.en-US.resources /template:bin\Debug\HelloWorld.exe

This is an example walkthrough of it MSDN with the above examples and more. Also you may want to read this blog post which explains its usage a bit further.

葮薆情 2024-08-13 04:21:40

这是我在互联网上看到的最简单的解决方案:

也很方便该解决方案的实施:
http://code.google.com/p/costura/wiki/HowItWorksEmbedTask

Here it is the simplest solution which I saw in the Internet:

also handy implementation of this solution:
http://code.google.com/p/costura/wiki/HowItWorksEmbedTask

怪我太投入 2024-08-13 04:21:40

另一种选择是将其他程序集作为 EmbededResource 嵌入。然后处理应用程序域AssemblyResolve,从这里您可以从资源中读取程序集并将其加载到运行时中。像下面这样:

public class HookResolver
{
    Dictionary<string, Assembly> _loaded;

    public HookResolver()
    {
        _loaded = new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    }

    System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        string name = args.Name.Split(',')[0];
        Assembly asm;
        lock (_loaded)
        {
            if (!_loaded.TryGetValue(name, out asm))
            {
                using (Stream io = this.GetType().Assembly.GetManifestResourceStream(name))
                {
                    byte[] bytes = new BinaryReader(io).ReadBytes((int)io.Length);
                    asm = Assembly.Load(bytes);
                    _loaded.Add(name, asm);
                }
            }
        }
        return asm;
    }
}

Another option is to embed the other assemblies as an EmbededResource. Then handle the app domains AssemblyResolve, from here you can read the assembly from the resource and load it into the runtime. Something like the following:

public class HookResolver
{
    Dictionary<string, Assembly> _loaded;

    public HookResolver()
    {
        _loaded = new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
    }

    System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        string name = args.Name.Split(',')[0];
        Assembly asm;
        lock (_loaded)
        {
            if (!_loaded.TryGetValue(name, out asm))
            {
                using (Stream io = this.GetType().Assembly.GetManifestResourceStream(name))
                {
                    byte[] bytes = new BinaryReader(io).ReadBytes((int)io.Length);
                    asm = Assembly.Load(bytes);
                    _loaded.Add(name, asm);
                }
            }
        }
        return asm;
    }
}
℉絮湮 2024-08-13 04:21:40

ILMerge will create a single exe file for your application. You can download it from Microsoft. It merges assemblies together and can internalize them so that the merged classes are set to internal. This is what I have used to create single file releases a number of times. It is pretty easy to integrate into your build process.

与他有关 2024-08-13 04:21:40

这是实现目标的简单(但非常实用)的方法。
在我看来,这是最容易维护的。
也就是说,每种意见都有其价值...

所有的魔力都发生在 Program.cs 和构建后事件中,该事件调用 ManageLanguage.cmd。

包含说明的 Github 项目示例: https://github.com/MensSana/CSharp-embed-卫星组件

Here's a simple (but very practical) way to reach your goal.
In my opinion, it's the easiest to maintain.
That said, every opinion has its value...

All the magic happens in Program.cs and the Post Build Event, which calls ManageLanguage.cmd.

Sample Github projet with instructions: https://github.com/MensSana/CSharp-embed-satellite-assemblies

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文