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

时间:2010-12-20 21:58:41

标签: c# dll resources assemblies embed

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

现在我想要A.exe加载,说“嘿我找不到这个文件”,然后查看资源文件并使用Assembly.Load(byte [])获取X.dll。我有代码重新魔术DLL,但这个代码永远不会被调用。

目前我有一个骨骼简单的项目,只是试图让它工作。它编译好了。当我运行它时,我在X.dll上得到一个FileNotFoundException。

我有:

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

但* CurrentDomain_AssemblyResolve *中的断点永远不会被击中。我立即得到一个FileNotFoundException。当然有一些我不知道的东西?

1 个答案:

答案 0 :(得分:10)

这个问题似乎与你想要达到的目标非常相似,而且它对提问者起作用。

Merge .dll into C# Assembly?

你有不同的做法吗?具体来说,如果您的目标是.NET Framework的旧版本,那么这可能是了解您的应用程序行为方式不同的原因。

另一个方向,使用Fusion Log Viewer之类的工具来分析尝试加载程序集时发生的情况。这可能会提供更多提示。如果您设法获取日志信息,将其发布在问题中可能有助于某人解决问题。

编辑:您的评论之后的另一种解释。

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

Main方法中,您正在引用其他dll中的类型。但是你是在 static 代码中进行的,即你在代码中明确使用了类型(而不是通过名称动态加载它)。

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

在编译FileNotFoundException时抛出了MainMain甚至没有开始运行,因此你的事件处理程序没有注册。

检查我是否正确的一种简单方法是将代码更改为:

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启动之前尝试加载程序集,以便编译它。