从内存加载.NET程序集而不是从硬盘加载

9
我尝试从内存中加载.NET程序集,而不是从磁盘中加载,但是遇到了困难。如果我编译程序集然后从磁盘中加载它(使用LoadFile或LoadFrom),那么应用程序就可以正常运行。
但是,如果我将编译后的程序集DLL文件作为嵌入式资源包含在项目中,然后使用Assembly.Load从资源流中加载字节,那么当应用程序继续运行时,我会遇到一系列随机错误。
这只是应用程序中八个程序集中的一个问题,其他所有程序集无论是从磁盘还是从内存中都可以正常工作。
谢谢您的帮助!

10
你需要提供更多关于错误的信息,以及它们发生的情况。 - rory.ap
1个回答

16

你没有提供足够的细节让我猜测你的问题是什么。不过,我可以介绍一下我使用的模式。

我处理嵌入依赖项的方法是使用 AssemblyResolve 事件。你只需一次性连接该事件,如果CLR在磁盘上找不到程序集,它将引发此事件。当事件被触发时,你就可以从资源清单中提取程序集位并调用 Assembly.Load

以下是代码示例:

internal class AssemblyResolver
{
  public static void Register()
  {
    AppDomain.CurrentDomain.AssemblyResolve +=
      (sender, args) =>
      {
        var an = new AssemblyName(args.Name);
        if (an.Name == "YourAssembly")
        {
          string resourcepath = "YourNamespace.YourAssembly.dll";
          Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourcepath);
          if (stream != null)
          {
            using (stream)
            {
              byte[] data = new byte[stream.Length];
              stream.Read(data, 0, data.Length);
              return Assembly.Load(data);
            }
          }
        }
        return null;
      }
  }
}

然后它可以像这样使用。

public static void Main()
{
  // Do not use any types from the dependent assembly yet.

  AssemblyResolver.Register();

  // Now you can use types from the dependent assembly!
}

我已经成功地使用了这个模式很多年了。有一些需要注意的地方,但大部分情况下它都运行良好。它肯定比使用 ILMerge 工具要好得多。


这是我看过的针对单个可执行应用程序最简单的解决方案。非常好。 - TheLegendaryCopyCoder
很遗憾,这个方法不再可行了。由于安全原因,现在使用Assembly.Load(data)总是失败。但是将数据写入磁盘上预期的文件名,然后加载它可以解决问题(目前)。我想从文件加载数据更加安全,因为这样可以让防病毒软件有机会阻止恶意数据的加载。 - Robert Jørgensgaard Engdahl
@RobertJørgensgaardEngdahl,异常(exception)中具体提到了哪些“安全原因”?您的目标是.NET Framework还是.NET Core? - Dai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接