C#:如何将DLL嵌入到资源文件中(程序目录中没有DLL副本)

发布于 2024-10-09 03:17:35 字数 606 浏览 1 评论 0原文

我有一个需要 X.dll 的 C# 应用程序(项目 A)。我已经将生成X.dll的项目添加到A中作为Visual Studio中的参考。我还将 X.dll 的发布版本作为二进制文件添加到 A 中的资源文件中。我已告诉项目 A 不要将 X.dll 复制到输出目录。

现在我想要加载 A.exe,说“嘿,我找不到这个文件”,然后查看资源文件并使用 Assembly.Load(byte[]) 取回 X.dll。我有重新放大 DLL 的代码,但是该代码从未被调用。

目前我有一个非常简单的项目,只是想让它发挥作用。编译就OK了。当我运行它时,我在 X.dll 上收到 FileNotFoundException。

我有:

[STAThread]
static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

但是 *CurrentDomain_AssemblyResolve* 中的断点永远不会被命中。我立即收到 FileNotFoundException。我肯定缺少什么东西吗?

I have a C# application (project A) that requires X.dll. I have added the project that produces X.dll to A as a reference in visual studio. I have also added the release build of X.dll to a resource file in A as a binary. I have told project A not to copy X.dll to the output directory.

Now I want A.exe to load, say "hey I can't find this file", then look in the resource file and use Assembly.Load(byte[]) get X.dll back. I have the code that re-magicifies the DLL back, however this code never get called.

Currently I have a bone simple project, just trying to get it to work. It compile OK. When I run it, I get a FileNotFoundException on X.dll.

I have:

[STAThread]
static void Main()
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}

But the breakpoint in *CurrentDomain_AssemblyResolve* never gets hit. I get a FileNotFoundException immediately. Surely there is something I a missing?

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

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

发布评论

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

评论(1

凉城凉梦凉人心 2024-10-16 03:17:35

这个问题似乎与您想要实现的目标非常相似,并且它对提问者有效。

将 .dll 合并到 C# 程序集中?

您是否在做不同的事情?具体来说,如果您的目标是较旧版本的 .NET Framework,这可能是理解应用程序行为不同的原因的提示。

另一个方向,使用诸如Fusion Log Viewer之类的工具来分析什么当您尝试加载程序集时发生了这种情况。这可能会给出更多提示。如果您设法获取日志信息,将其发布在问题中可能会帮助别人弄清楚。

编辑:根据您的评论进行另一个解释。

好吧,现在我想我知道问题是什么了。

在您的 Main 方法中,您引用了另一个 dll 中的类型。但是您是在静态代码中执行此操作,即您在代码中显式使用该类型(而不是通过名称动态加载它)。

为什么这是一个问题? CLR 尝试加载您的程序集,以便 JIT Main 本身。

编译 Main 时抛出了 FileNotFoundExceptionMain 甚至没有开始运行,因此您的事件处理程序没有注册。

检查我是否正确的一个简单方法是将代码更改为如下所示:

static public void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += MyEventHandler;
    MyMain();
}

// The CLR will actually try to load your assembly before even starting the execution
// of this method. It needs the assembly in order to JIT the method because it has to 
// know the Thing type.
static public void MyMain()
{
    using(var thing = new Thing())
    {
         // ...
    }
}

重要的区别是 Main 不依赖于另一个程序集,因此 JIT 和运行不会有问题它。

MyMain 进行 JIT 时,您的事件处理程序已经就位,因此您可以手动加载程序集。

顺便说一句,为了避免另一个可能的类似陷阱,请确保定义 Main 的类没有任何具有来自其他程序集的类型的字段,因为在这种情况下,CLR将尝试在 Main 启动之前加载程序集,以便对其进行编译。

This question seems to be very similar to what you are trying to achieve, and it worked for the asker.

Merge .dll into C# Assembly?

Are you doing something differently? Specifically, if you're targetting an older version of the .NET Framework, maybe that's a hint for understanding why your application is behaving differently.

Another direction, use a tool such as Fusion Log Viewer to analyze what was going on when you tried to load the assembly. This may give some more hints. If you manage to get log information, posting it in the question may help someone figure it out.

EDIT: Another explanation, following your comment.

Well, now I think I know what the problem is.

In your Main method, you are refering to the type in the other dll. But you are doing it in static code, i.e. you use the type explicitly in the code (as opposed to loading it dynamically by its name).

Why is this a problem? The CLR tries to load your assembly in order to JIT Main itself.

Your FileNotFoundException was thrown while Main was being compiled. Main didn't even start running, and therefore your event handler wasn't registered.

A simple way to check if I'm right is to change the code to something like this:

static public void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += MyEventHandler;
    MyMain();
}

// The CLR will actually try to load your assembly before even starting the execution
// of this method. It needs the assembly in order to JIT the method because it has to 
// know the Thing type.
static public void MyMain()
{
    using(var thing = new Thing())
    {
         // ...
    }
}

The important difference is that Main has no dependency on another assembly, so there will be no problem to JIT and run it.

By the time MyMain is being JIT'ed, your event handler is already in place so you can manually load the assembly.

By the way, to avoid another possible similar pitfall, make sure that the class in which Main is defined doesn't have any field with a type from the other assembly, because in this case also, the CLR will try loading the assembly before Main starts, in order to compile it.

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