Lazy加载程序启动后放在文件系统上的DLL [英] Lazy load a DLL that was placed on the filesystem after the program has been started

查看:214
本文介绍了Lazy加载程序启动后放在文件系统上的DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用C#构建一个自动化线束,并尝试执行以下操作:




  • 引导线束

  • 安装可执行文件

  • 使用可执行文件放置的几个DLL来建立与exe连接的基础设施的连接(大型,复杂的软件系统) li>


我需要使用的DLL是一些静态类,执行自己的引导过程以连接到其余的服务器在测试环境中。我试过的是创建一个类似于这样的连接类:

  using CompanyName.Framework; 

命名空间TestNamespace {
public class ProductConnectorClass {
//初始化连接到产品并做东西
public ProductConnectorClass(){
var connection = CompanyName.Framework.Initialize(...);

//做连接的东西
connection.RunStuff();
}
}
}

包含< b> CompanyName.Framework 命名空间在测试框架首次启动时无法访问。它是通过代码从另一个类看起来像这样的复制:

 命名空间TestNamespace {
public class TestRunnerClass {
public TestRunnerClass(){
//伪代码在这里,所以你得到的想法:
CopyMsiToHost(msiRemotePath,msiLocalPath);
InstallMsi(msiLocalPath);
CopyDllsToTestHarnessDir();
ProductConnectorClass pcc = new ProductConnectorClass();
}
}
}

代码命中 ProductConnectorClass pcc = new ProductConnectorClass(); 行,我收到一个例外:

  FileNotFoundException未处理
无法加载文件或程序集CompanyName.Framework,Version = 6.0.0.0,Culture = neutral,PublicKeyToken = XXXXXXXXXXXXXXXX或其依赖项之一。该系统找不到指定的文件。

由于我在DLL上设置了具体版本:False 在我的测试项目中,我的操作假设是.NET Lazy加载DLL(在我看来,这意味着在需要的时候搜索并加载它们)。在这一点上,我正在寻找一种简单的方法来获取一个运行的.NET程序,以便在进程开始运行后找到一个已经放置的DLL。



注意1:如果在DLL已经到位之后重新启动该过程,它将加载正常。看起来它只是在启动时扫描DLL,这仍然让我困惑。



注2:这个SO回答给了我一些关于如何加载DLL的信息,但没有完全回答我的问题。简要说明,如果.NET尝试加载DLL,并且它失败,它将不会尝试再次加载它。在我的情况下,我不希望在DLL上进行加载尝试,因为引用了DLL的类尚未被实例化。

解决方案

从我执行的测试项目的实验中,我需要执行代码的模块化,以使其工作。在任何情况下,我都不能引用目前不存在的DLL,启动我的程序,然后下载DLL。



这是我解决方案的步骤: p>


  • 在我的自动化解决方案中将我的公共类和接口重构到自己的DLL项目

  • 创建另一个DLL项目('TestLogic')在我的解决方案中,使用我在程序启动后放下的DLL

  • 当我需要使用程序启动后放置的DLL时,我使用反射加载TestLogic dll并执行测试



为了引用,我做了一个google搜索C#late load dll,发现这个msdn社交讯息有一些有用的建议。以下是该线程中最有帮助的回复的复制/粘贴/修改:


  1. 移动引用所安装的DLL的所有代码在测试框架开始完全独立的程序集之后。我们称之为TestLogicAssembly。

  2. 创建一个新程序集并定义界面。我们将称之为TestInterfaceAssembly。

  3. 在您的主DLL和TestLogicAssembly中引用TestInterfaceAssembly。

  4. 在TestLogicAssembly中创建一个实现接口在TestInterfaceAssembly中创建。

  5. 不要从主应用程序引用TestLogicAssembly。

  6. 在运行时,检查是否放置了DLL作为测试框架的安装步骤的一部分实际安装。如果是,请使用Assembly.Load加载TestLogicAssembly,然后找到实现第2个定义的接口的类型。使用Activator.CreateInstance创建此类型的实例,并将其转换为您创建的接口。


I am building an automation harness using C# and am trying to do the following:

  • Bootstrap the harness
  • Install the executable
  • Use a couple of DLLs that the executable lays down to establish a connection to the infrastructure that the exe connects to (large, complex software system)

The DLLs that I need to use are a few static classes that perform their own 'bootstrap' process to get connected to the rest of the servers in the test environment. What I have tried is creating a connection class that looks like this:

using CompanyName.Framework;

namespace TestNamespace{
    public class ProductConnectorClass{
        // Initialize a connection to the product and do stuff
        public ProductConnectorClass(){
            var connection = CompanyName.Framework.Initialize(...);

            // Do stuff with the connection
            connection.RunStuff();
        }
    }
}

The DLL that contains the CompanyName.Framework namespace is not accessible when the test framework is first started. It is copied via code from another class that looks lomething like this:

namespace TestNamespace{
    public class TestRunnerClass{
        public TestRunnerClass(){
            // pseudo code here, so you get the idea:
            CopyMsiToHost(msiRemotePath, msiLocalPath);
            InstallMsi(msiLocalPath);
            CopyDllsToTestHarnessDir();
            ProductConnectorClass pcc = new ProductConnectorClass();
        }
    }
}

It is when the code hits the ProductConnectorClass pcc = new ProductConnectorClass(); line that I get an exception:

FileNotFoundException was unhandled
Could not load file or assembly 'CompanyName.Framework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=XXXXXXXXXXXXXXXX' or one of its dependencies. The system cannot find the file specified.

This puzzles me since I have set Specific Version: False on the DLL in my test project and I am operating under the assumption that .NET Lazy-loads DLLs (in my mind that means search for and load them at the time they are needed). At this point I am looking for a simple way to get a running .NET program to find a needed DLL that has been placed after the process started running.

Note 1: If I restart the process after the DLL is already in place, it loads fine. It looks like it is only scanning for DLLs on startup, which still puzzles me.

Note 2: This SO answer gives me some information about how DLLs are loaded, but doesn't fully answer my question. The synopsis is that if .NET has tried to load the DLL and it fails that it won't try to load it again. In my case I don't expect that a load attempt has been made on the DLL since the class where the DLL is referenced has not been instantiated yet.

解决方案

From experiments in test projects that I have performed, it appears that I need to perform modularization of my code in order to get this to work. In no case am I able to reference a dll that does not currently exist, start my program then drop down the DLL.

Here are my steps to a solution:

  • Refactor my common classes and interfaces to their own DLL project in my Automation solution
  • Create another DLL project ('TestLogic') in my solution that uses the DLL I lay down after the program has started
  • When I need to use the DLL that is laid down after the program starts, I use reflection to load the TestLogic dll and perform the tests

For reference I did a google search for 'C# late load dll' and found this msdn social post with some helpful advice. Here is a copy/paste/modify of the most helpful reply from that thread:

  1. Move all the code that references the DLLs that are installed after the test framework starts to a completely separate assembly. We'll call this "TestLogicAssembly".
  2. Create a new assembly and define an interface. We'll call this "TestInterfaceAssembly".
  3. Reference TestInterfaceAssembly in both your main DLL and your TestLogicAssembly.
  4. Create a class in TestLogicAssembly that implements the interface created in TestInterfaceAssembly.
  5. Don't reference TestLogicAssembly from your main application.
  6. At runtime, check to see if the DLLs that are laid down as part of the install step of the test framework are actually installed. If they are, use Assembly.Load to load the TestLogicAssembly, then find the type that implements the interface defined in number 2. Use Activator.CreateInstance to create an instance of this type, and cast it to the interface you created.

这篇关于Lazy加载程序启动后放在文件系统上的DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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