C#:如何将DLL嵌入资源文件(程序目录中没有dll拷贝) [英] C#: How to embed DLL into resourcefile (no dll copy in program directory)

查看:336
本文介绍了C#:如何将DLL嵌入资源文件(程序目录中没有dll拷贝)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



现在我想要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工作。



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



你做的不同吗?具体来说,如果您要定位较旧版本的.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.

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.

这篇关于C#:如何将DLL嵌入资源文件(程序目录中没有dll拷贝)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆