简体   繁体   English

.NET引用来自其他位置的DLL

[英].NET Reference dll from other location

I'm making a program depending on some DLLs included in a third party program. 我正在制作一个程序,取决于第三方程序中包含的一些DLL。 I'm not allowed to distribute these DLLs myself. 我不允许自己分发这些DLL。 The third party program must be installed for my program to work. 必须安装第三方程序才能使我的程序正常运行。

How can i make a reference to these DLLs? 我如何引用这些DLL? I know the exact location of them through a registry key set by the program. 我通过程序设置的注册表项知道它们的确切位置。

I have tried to add the files in Project->References and set CopyLocal to false but when i start i then get a FileNotFoundException "Could not load file or assembly". 我试图在Project-> References中添加文件并将CopyLocal设置为false但是当我启动i然后得到FileNotFoundException“无法加载文件或程序集”。

I have tried to add an event to AppDomain.CurrentDomain.AssemblyResolve and load the files there but the problem is that i get the exception before my program even starts. 我试图向AppDomain.CurrentDomain.AssemblyResolve添加一个事件并在那里加载文件,但问题是我在程序启动之前得到了异常。 Even if i put a breakpoint on the first line the exception will be thrown before the breakpoint is hit. 即使我在第一行放置断点,也会在断点被触发之前抛出异常。

From C# 3.0 in a Nutshell , 3rd edition, by Joseph and Ben Albahari , p. 来自C#3.0 in a Nutshell ,3rd edition,Joseph和Ben Albahari ,p。 557-558: 557-558:

Deploying Assemblies Outside the Base Folder 在基本文件夹之外部署程序集

Sometimes you might choose to deploy assemblies to locations other than the application base directory [...] To make this work, you must assist the CLR in finding the assemblies outside the base folder. 有时您可能会选择将程序集部署到应用程序基目录以外的位置 [...] 为了使其工作,您必须协助CLR查找基本文件夹之外的程序集。 The easiest solution is to handle the AssemblyResolve event. 最简单的解决方案是处理AssemblyResolve事件。

(We can ignore the fact that in your case, someone other than you is deploying the assemblies.) (我们可以忽略这样一个事实:在您的情况下,除您之外的其他人正在部署程序集。)

Which you tried. 你试过哪个。 But a very important clue follows somewhat later. 但是后来有一个非常重要的线索。 Read the two code comments: 阅读两个代码注释:

 public static void Loader { static void Main(string[] args) { AppDomain.CurrentDomain.AssemblyResolve += FindAssem; // We must switch to another class before attempting to use // any of the types in C:\\ExtraAssemblies: Program.Go(); } static Assembly FindAssem(object sender, ResolveEventArgs args) { string simpleName = new AssemblyName(args.Name).Name; string path = @"C:\\ExtraAssemblies\\" + simpleName + ".dll"; if (!File.Exists(path)) return null; return Assembly.LoadFrom(path); } } public class Program { public static void Go() { // Now we can reference types defined in C:\\ExtraAssemblies } } 

As you see, the class where you resolve the external assemblies must not refer to any type from any of the external DLLs anywhere . 如您所见, 解析外部程序集的类不得在任何地方引用任何外部DLL中的任何类型 If it did, code execution would stop way before your AssemblyResolve ever gets a chance to run. 如果是这样,代码执行将在AssemblyResolve有机会运行之前停止。

Your app bombs because the JIT compiler is the first one that needs to load the assembly. 您的应用程序炸弹,因为JIT编译器是第一个需要加载程序集的程序。 You'll need to carefully avoid using types from the assembly in your Main() method. 您需要小心避免在Main()方法中使用程序集中的类型。 That's not hard to do, just write another Main method and give it an attribute that tells the jitter that it should never inline that method. 这并不难,只需编写另一个Main方法并给它一个属性,告诉抖动它永远不应该内联该方法。 Without the attribute it may still bomb in the Release build when the optimizer inlines the method. 如果没有该属性,当优化程序内联该方法时,它仍可能在Release版本中炸弹。 Like this: 像这样:

using System;
using System.Runtime.CompilerServices;

class Program {
    static void Main(string[] args) {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
        DelayedMain(args);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void DelayedMain(string[] args) {
        // etc..
    }


    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
        // etc...
    }
}

Before you commit doing it this way, do contact the vendor and ask for recommendations. 在您以这种方式提交之前,请与供应商联系并寻求建议。 There has to be an easier way to exercise your license rights. 必须有一种更简单的方式来行使您的许可权利。 The GAC would be a common choice, maybe you just need to run gacutil on your dev machine. GAC是一个常见的选择,也许您只需要在您的开发机器上运行gacutil。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM