C#:如何将DLL嵌入资源文件(程序目录中没有dll拷贝) [英] C#: How to embed DLL into resourcefile (no dll copy in program directory)
问题描述
现在我想要A.exe加载,说嘿我找不到这个文件,然后查看资源文件并使用Assembly.Load(byte [ ])得到X.dll回来。我有代码重新魔术化的DLL回来,但这个代码永远不会被调用。
目前我有一个骨骼简单的项目,只是想让它上班。它编译好了当我运行它,我得到一个FileNotFoundException X.dll。
我有:
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve + = new ResolveEventHandler(CurrentDomain_AssemblyResolve);
}
但是* CurrentDomain_AssemblyResolve *中的断点永远不会被击中。我立即得到FileNotFoundException。确实有一些我错过的东西?
这个问题似乎与你想要实现的非常相似,为asker工作。
你做的不同吗?具体来说,如果您要定位较旧版本的.NET Framework,或许这是一个提示,以了解您的应用程序的行为方式不同。
另一个方向,使用工具例如 Fusion Log Viewer ,以分析当您尝试过的时候发生了什么加载组件。这可能会提供更多的提示。如果您设法获取日志信息,则可以在该问题中发布信息可能会帮助某人弄清楚。
编辑:遵循评论后的另一个解释。 >
嗯,现在我想我知道问题是什么。
在您的主要
方法中,您将引用另一个dll中的类型。但是您正在使用静态代码,即您在代码中使用类型(而不是通过其名称动态加载)。
<为什么这是一个问题? CLR尝试加载您的程序集,以便JIT
主要
本身。 您的 FileNotFoundException
被抛出,而 Main
正在编译。 Main
甚至没有开始运行,因此您的事件处理程序未注册。
一种简单的方式检查我是否正确的是将代码更改为这样:
static public void Main(string [] args)
{
AppDomain.CurrentDomain.AssemblyResolve + = MyEventHandler;
MyMain();
}
// CLR实际上会尝试加载你的程序集,甚至在这个方法开始执行
//之前。它需要汇编以便JIT的方法,因为它必须
//知道Thing类型。
static public void MyMain()
{
using(var thing = new Thing())
{
// ...
}
重要的区别是 Main
没有依赖于另一个程序集,所以JIT将不会出现问题并运行它。
到时候 MyMain
正在JIT,你的事件处理程序已经到位,所以你可以手动加载程序集。
顺便说一句,为了避免另外一个类似的错误,make定义 Main
的类不具有来自另一个程序集的类型的任何字段,因为在这种情况下,CLR也会尝试加载程序集主要
开始,以便编译它。
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?
This question seems to be very similar to what you are trying to achieve, and it worked for the asker.
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.
这篇关于C#:如何将DLL嵌入资源文件(程序目录中没有dll拷贝)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!