是否可以在运行时切换 DLL 以使用不同的版本?

2023-11-27

我有一个应用程序,其中包含许多连接到许多不同 I/O 设备的插件 (MEF)。大多数这些插件都有许多托管和非托管 dll。

一家制造商最近发布了新固件和新驱动程序。 API 保持不变。

我认为我可以将两个 dll 版本包含在单独的资源文件夹中,并在应用程序启动时将所需的集复制到输出文件夹中。

(我想我可以制作插件的第二个副本并找出加载正确副本的方法,但我认为复制 DLL 可能会更容易 - 特别是考虑到插件代码未更改)

这是行不通的。

static MyClass() // static constructor
{
    // required version?
    if (envvar.Equals("4") )
    {
        path = "ver4.1.1";
    }
    else
    {
        path = "ver2.5.1";
    }

    // location of drivers
    path = Path.Combine("./Prj/QX", path);
    string[] files = Directory.GetFiles(path);

    // Copy the files and overwrite destination files if they already exist.
    foreach (string s in files)
    {
        string fileName = Path.GetFileName(s);
        string destFile = Path.Combine(".", fileName);
        File.Copy(s, destFile, true);
    }

    // force load of assemby
    Assembly assy = LoadWithoutCache("driver.dll");
    string fn = assy.FullName;
}

static Assembly LoadWithoutCache(string path)
{
    using (var fs = new FileStream(path, FileMode.Open))
    {
        var rawAssembly = new byte[fs.Length];
        fs.Read(rawAssembly, 0, rawAssembly.Length);
        return Assembly.Load(rawAssembly);
    }
}

该错误消息表明原始 DLL 已加载或应该已加载但无法加载。

Could not load file or assembly 'driver, Version=1.5.77, Culture=neutral, PublicKeyToken=983247934' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

有什么方法可以实现我的目标,还是我必须构建 2 个单独版本的应用程序?

EDIT我还应该说,没有必要同时加载两个 DLL。使用一个导致加载一个或另一个 DLL 的参数来启动应用程序就足够了。


实现这一目标的一种(复杂)方法是:

1. 使用 FileSystemWatcher(FSW) 监视文件夹

FSW 检测程序集是否被更改或删除。

2. 将程序集加载到仅反射上下文

只能检查加载到此上下文中的程序集! 通过获取程序集的类型并检查类型是否实现您的 PluginInterface,确保程序集类型实现 PluginInterface。

3. 使用以下命令将程序集加载到单独的 AppDomain 中卷影复制

由于您只能卸载 AppDomain 及其所有程序集,因此您将每个插件程序集加载到其自己的 AppDomain 中。这样就可以卸载插件的AppDomain。

请务必终止插件的所有进程/线程!

卷影复制通过将程序集复制到临时路径来确保原始文件的更改。

4. 跟踪加载的程序集

将成功加载的程序集的路径放入列表中。 这使得更容易检测程序集是否需要加载/重新加载。

5. 处理FSW事件

检查哪个 .dll 被更改/删除以卸载程序集,或者是否检测到新程序集以加载它。

6. 转到步骤 2


问候, 布莱克根斯

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否可以在运行时切换 DLL 以使用不同的版本? 的相关文章

随机推荐

  • 如何在 Three.js 中使用多个纹理并将其与自定义值混合?

    在 Three js 中 是否可以创建一种包含多个纹理的材质 着色器 每个纹理都有自己的细节 将它们混合在一起并分配给几何体 我想使用箔压花或局部紫外线上光等多种精加工技术来模拟纸张表面 我想要实现的是一种具有以下特性的材料 Base la
  • 将字符插入 SQL 字符串

    我有一个 nvarchar 列 我需要在字符串内的固定点插入连字符 连字符需要位于最右边的字符和下一个字符之间 并再次位于右侧第三个位置 例如 列值为 0000050704 我需要它是 0000050 70 4 或值为 0555256321
  • AndroidTextureView/绘图/绘画性能

    我正在尝试使用以下命令制作绘图 绘画应用程序TextureView在安卓上 我想要支持高达 4096x4096 像素的绘图表面 这对于我的最小目标设备 我用于测试的 来说似乎是合理的 即 Google Nexus 7 2013 它具有不错的
  • 匿名类的多重继承

    匿名类如何实现两个 或更多 接口 或者说 怎样才能both扩展一个类and实现一个接口 例如 我想创建一个扩展两个接口的匿名类的对象 Java 10 var is used since I don t know how to specify
  • 如何更改java DNS服务提供商

    我正在构建一个快速的网络爬虫 并且需要多线程 DNS 解析 因此我选择了一个名为的多线程 DNS 服务提供商dnsjava 不幸的是 我不知道如何替换默认的 DNS 服务提供商 我回顾了README文件 dnsjava 但说明不是很详细 替
  • 如何在 TFS 中撤消前员工的签出

    在我们的TFS源控制服务器上 很多源文件被人们签出 不再使用 是否有一种集中方式可以撤消对 TFS 中所有文件的签出 我什至不确定它们是否存在于 Active Directory 中 最好的办法是使用命令行工具 tf exe 或Attric
  • 在 MediaSource HTML5 中播放 MediaRecorder 块 - 视频冻结

    我有这个简单的代码来获取视频流块并在 MediaSource 中播放它们 我看视频 但有时会停止 它可能会工作几秒钟或几分钟 但最终它在某个时刻停止了 chrome media internals 显示没有错误 这里有什么问题吗 navig
  • 如何通过克隆当前本地环境来创建virtualenv?

    假设我有一个 python 解释器 在我的本地系统上安装了许多模块 并且它已经被调整为可以正常工作 现在我想创建一个 virtualenv 来冻结这些 这样它们就不会在将来升级时被破坏 我怎样才能做到呢 谢谢 我不能使用pip freeze
  • 如何为表单设置点击事件?

    我有一个 C 表单 我们称之为 MainForm 上面有许多自定义控件 我希望每当有人单击表单时都会触发 MainForm OnClick 方法 无论单击是发生在表单上还是单击是在自定义控件之一上 我正在寻找类似于表单的 KeyPrevie
  • 为什么我会收到“仅允许在事务内查询祖先查询”错误

    boolean r ofy transact new Work
  • PySide:将 QItemSelectionModel 与 QListView 一起使用时出现段错误(?)

    与此完全相同的问题 连接 QTableView SelectionChanged 信号会与 PyQt 产生段错误 我有一个 QListView 我想在选择一个项目时调用一个函数 self server list QtGui QListVie
  • AsyncTask API 在 Android 11 中已弃用。有哪些替代方案?

    Google 在 Android 11 中弃用 Android AsyncTask API 并建议使用java util concurrent反而 你可以查看提交here deprecated Use the standard code j
  • 如何检测浏览器窗口是否获得焦点?

    我的页面应该仅在窗口位于后台时发出通知声音 我可以追踪window onfocus and window onblur当焦点状态发生变化时要注意的事件 但是 我不知道该窗口是否会加载焦点 因为它可能会加载到后台选项卡中 在获得提示之前 如何
  • 如何将 Ruby C 扩展封装在 Ruby Gem 中?

    我找不到很多关于此的文档 如何打包 gem 以便在安装 gem 时编译 C 扩展 我特别想这样做 在 Linux 和 MacOSX 上 我想在 gem install 上编译 C 扩展 在 Windows 上我想简单地安装一个预编译的 so
  • django 将 ManyToMany 字段/表添加到现有架构,相关名称错误

    我有一个带有模型的现有项目 用户和书籍 我想将 ManyToMany M2M 字段添加到现有模型 Books 中 但syncbb 命令不执行此操作 详细信息 书籍已经有一个映射到用户的 FK 字段 我想添加一个也映射到用户的新 M2M 字段
  • iPhone 应用程序的 Facebook 访问令牌服务器端验证

    我正在开发基于与服务器通信的iPhone应用程序 我想使用Facebook身份验证机制 基本上 我认为它应该像这样工作 在我的 iPhone 应用程序中 用户使用他的电子邮件和密码登录 Facebook 用户允许相关 Facebook 应用
  • 如何在 Java 正则表达式中表达“:”但前面不加“\”?

    如何在Java正则表达式中表达 前面没有 例如 我想搜索 但前提是它前面没有直接 我怎样才能做到这一点 Use a 消极回顾
  • 使用 JavaScript 在 HTML 页面中处理会话 [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我们可以借助 javascript 在 HTML 页面中进行会话处理吗 如果是 怎么办 如果没有 为什么 javascript仅支持cookie 您可以将它们设置为跟踪用户会话
  • PLS-00201:必须声明标识符 UTIL_FILE

    我正在尝试从安装在 Windows Server 2008 计算机上的 Oracle Enterprise Express 将查询数据导出到 csv 文件中 我找到了这个解决方案 http asktom oracle com pls ask
  • 是否可以在运行时切换 DLL 以使用不同的版本?

    我有一个应用程序 其中包含许多连接到许多不同 I O 设备的插件 MEF 大多数这些插件都有许多托管和非托管 dll 一家制造商最近发布了新固件和新驱动程序 API 保持不变 我认为我可以将两个 dll 版本包含在单独的资源文件夹中 并在应