C#:如何将DLL嵌入到资源文件中(程序目录中没有DLL副本)
我有一个需要 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这个问题似乎与您想要实现的目标非常相似,并且它对提问者有效。
将 .dll 合并到 C# 程序集中?
您是否在做不同的事情?具体来说,如果您的目标是较旧版本的 .NET Framework,这可能是理解应用程序行为不同的原因的提示。
另一个方向,使用诸如Fusion Log Viewer之类的工具来分析什么当您尝试加载程序集时发生了这种情况。这可能会给出更多提示。如果您设法获取日志信息,将其发布在问题中可能会帮助别人弄清楚。
编辑:根据您的评论进行另一个解释。
好吧,现在我想我知道问题是什么了。
在您的
Main
方法中,您引用了另一个 dll 中的类型。但是您是在静态代码中执行此操作,即您在代码中显式使用该类型(而不是通过名称动态加载它)。为什么这是一个问题? CLR 尝试加载您的程序集,以便 JIT
Main
本身。编译
Main
时抛出了FileNotFoundException
。Main
甚至没有开始运行,因此您的事件处理程序没有注册。检查我是否正确的一个简单方法是将代码更改为如下所示:
重要的区别是
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 whileMain
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:
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 beforeMain
starts, in order to compile it.