允许同一 COM 库的多个版本

2023-12-23

我编写了一个 C# 程序和库,允许用户更轻松地使用特定专有模拟器的 COM 接口。

目前,我必须为我希望支持的每个版本的模拟器构建和分发不同版本的 C# 库。开发模拟器的公司定期发布新版本,每个新版本都会有一个递增的主版本号。据我所知,版本之间的 COM 接口尚未发生任何变化,因此从我的角度来看,调用和行为都是相同的。但是,如果我针对模拟器版本 9.0 构建库和安装程序,并且用户安装了版本 10.0,则我的 C# 程序无法找到模拟器的 COM 接口。 (即使对模拟器进行较小的升级也会导致 COM 接口的主要版本发生变化。)因此,我必须针对每个受支持的模拟器版本构建我的库。这很烦人,我宁愿分发一个在安装时正确查找并链接到最新模拟器的库。

看来必须有办法做到这一点。我认为这个页面可能描述了该方法:如何:包装类型库的多个版本 http://msdn.microsoft.com/en-us/library/1565h6hc.aspx。但这似乎对我不起作用。

当然,也有可能是我没有做对。我按照说明获取了两个版本的 COM 接口的 .il 文件。 9.0 和 10.0。但我对下一步感到困惑,找不到例子:

使用文本编辑器,在 Tlbimp.exe 添加的属性下方插入第二个 PrimaryInteropAssemblyAttribute 属性。包括代表第二类型库版本的主要版本号和次要版本号。

我不确定是否应该复制程序集块,或者只是复制块内的行(它没有我可以看到的版本信息。)所以我像这样复制了程序集块:

enter code here
.assembly Interop.Happ
{
  .custom instance void 
    [mscorlib]System.Runtime.InteropServices.ImportedFromTypeLibAttribute::.ctor(string) = ( 01 00 04 48 61 70 70 00 00 )
  .custom instance void 
    [mscorlib]System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute::.ctor(int32, int32) = ( 01 00 09 00 00 00 00 00 00 00 00 00 ) 

   ////////////// [SNIP] ///////////////
  .ver 9:0:0:0
}
.assembly Interop.Happ
{
  .custom instance void
    [mscorlib]System.Runtime.InteropServices.ImportedFromTypeLibAttribute::.ctor(string) = ( 01 00 04 48 61 70 70 00 00 )
  .custom instance void 
    [mscorlib]System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute::.ctor(int32, int32) = ( 01 00 0A 00 00 00 00 00 00 00 00 00 ) 

  ////////////// [SNIP] //////////////
  .ver 10:0:0:0
}
.module Interop.Happ.dll

这不起作用,但我看不出我的其他解释如何可能。谁能看到我做错了什么吗?我是否完全走错了路,或者我只是组合了 .il 文件的错误部分?


我们为我们的产品解决了这个问题,不使用tlbimp.exe并提供定制包装。

我们的包装器仅为接口提供 .NET 定义,忽略类型库和组件类。用户必须使用 Activator API 从 ProgID 获取实例,当然,ProgID 可以成为其应用程序的配置参数。

这是可以管理的,因为接口是不可变的,因此我们必须为每个接口只创建一次包装类,即使实现不断发展。

包装示例:

[ComImport, Guid("PUT-GUID-HERE")]
public interface IProdistLogger
{
    [DispId(1000)]
    string Name { [return: MarshalAs(UnmanagedType.BStr)] get; }

    [DispId(1001)]
    void LogSimple (long level, [MarshalAs(UnmanagedType.BStr)] string message, object location);
}

[ComImport, Guid("PUT-GUID-HERE")]
public interface IProdistLoggingHierarchy
{
    [DispId(1000)]
    string Type { [return: MarshalAs(UnmanagedType.BStr)] get; }

    [DispId(1001)]
    IProdistLogger CreateLogger ([MarshalAs(UnmanagedType.BStr)] string name);
}

[ComImport, Guid("PUT-GUID-HERE")]
public interface IProdistLogging
{
    [DispId(1000)]
    IProdistLoggingHierarchy CreateHierarchy ([MarshalAs(UnmanagedType.BStr)] string type, object configuration);
}

客户端示例:

public class Program
{
    public static void Main (string[] args)
    {
        IProdistLogging logging = (IProdistLogging)System.Activator.CreateInstance(Type.GetTypeFromProgID("prodist.logging.Logging.5.4"));
        IProdistLoggingHierarchy hierarchy = logging.CreateHierarchy("log4cxx", null);
        return;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

允许同一 COM 库的多个版本 的相关文章

  • 具有可绑定属性的自定义视图未在 Xamarin.Forms SAP 上正确绑定

    我有一个复选框 应该触发按钮的 IsEnabled 事件 但不知何故 应该执行的命令永远不会正确绑定并因此执行 这是 CheckBox xaml cs 控件 中的可绑定属性 public static readonly BindablePr
  • Accept() 是线程安全的吗?

    我目前正在用 C 语言为我正在做的课程编写一个简单的网络服务器 我们的一项要求是实现一个线程池来使用 pthread 处理连接 我知道我将如何粗略地执行此操作 在主线程中调用accept并将文件描述符传递给freee线程 但是我的朋友建议了
  • 将图像文件从网址复制到本地文件夹?

    我有该图像的网址 例如 http testsite com web abc jpg http testsite com web abc jpg 我想将该 URL 复制到 c images 中的本地文件夹中 而且当我将该文件复制到文件夹中时
  • 使用API​​隐藏程序标题栏

    它可以使用 c 和 windows api 删除窗口控制台标题栏 如果是的话如何 请 这个简单的应用程序隐藏并显示其所在控制台的标题栏 它会立即将控制台标题更改为 guid 以查找窗口句柄 然后 它使用 ToggleTitleBar 使用找
  • C#中Enum中定义的value__是什么

    What value 可能在这里 value MSN ICQ YahooChat GoogleTalk 我运行的代码很简单 namespace EnumReflection enum Messengers MSN ICQ YahooChat
  • 在简单注入器中注册具有多个构造函数和字符串依赖项的类型

    我正在尝试弄清楚如何使用 Simple Injector 我在项目中使用了它 注册简单服务及其组件没有任何问题 但是 当组件具有两个以上实现接口的构造函数时 我想使用依赖注入器 public DAL IDAL private Logger
  • 允许使用什么类型的内容作为 C 预处理器宏的参数?

    老实说 我很了解 C 编程语言的语法 但对 C 预处理器的语法几乎一无所知 尽管我有时在编程实践中使用它 所以问题来了 假设我们有一个简单的宏 它扩展为空 define macro param 可以放入宏调用构造中的语法有哪些限制 调用宏时
  • 从事务范围调用 WCF 服务方法

    我有这样的代码 using TransactionScope scope TransactionScopeFactory CreateTransactionScope some methodes calls for which scope
  • 错误左值需要作为赋值C++的左操作数

    整个程序基本上只允许用户移动光标 如果用户位于给定的坐标范围 2 2 内 则允许用户键入输入 我刚刚提供了一些我认为足以解决问题的代码 我不知道是什么导致了这个问题 你能解释一下为什么会发生吗 void goToXY int int 创建一
  • 不兼容的类型 - 是因为数组已经是指针吗?

    在下面的代码中 我创建一个基于书籍结构的对象 并让它保存多个 书籍 我设置的是一个数组 即定义 启动的对象 然而 每当我去测试我对指针的了解 实践有帮助 并尝试创建一个指向创建的对象的指针时 它都会给我错误 C Users Justin D
  • 如何使用收益返回和递归获得字母的每个组合?

    我有几个像这样的字符串列表 可能有几十个列表 1 A B C 2 1 2 3 3 D E F 这三个仅作为示例 用户可以从几十个具有不同数量元素的类似列表中进行选择 再举个例子 这对于用户来说也是一个完全有效的选择 25 empty 4 1
  • 相当于 C# 中 Java 的“ByteBuffer.putType()”

    我正在尝试通过从 Java 移植代码来格式化 C 中的字节数组 在 Java 中 使用方法 buf putInt value buf putShort buf putDouble 等等 但我不知道如何将其移植到 C 我尝试过 MemoryS
  • 纯虚函数可能没有内联定义。为什么?

    纯虚函数是那些虚函数并且具有纯说明符 0 第 10 4 条第 2 款C 03 的内容告诉我们什么是抽象类 顺便说一句 如下 注意 函数声明不能 同时提供纯说明符和定义 尾注 示例 struct C virtual void f 0 ill
  • ASP.NET Core Razor Page 多路径路由

    我正在使用 ASP NET Core 2 0 Razor Pages 不是 MVC 构建系统 但在为页面添加多个路由时遇到问题 例如 所有页面都应该能够通过 abc com language 访问segment shop mypage 或
  • C++ [Windows] 可执行文件所在文件夹的路径[重复]

    这个问题在这里已经有答案了 我需要访问一些文件fstream在我的 Windows 上的 C 应用程序中 这些文件都位于我的exe文件所在文件夹的子文件夹中 获取当前可执行文件的文件夹路径的最简单且更重要的 最安全的方法是什么 Use 获取
  • 使用 Chrome 和 Selenium 设置 LocalStorage

    我正在尝试使用 OpenQA Selenium 和 Chrome 设置本地存储键和值 我认为这相当微不足道 但我似乎无法让它发挥作用 我对 C 很陌生 所以我可能错过了一些东西 无论如何 我有这个功能 public static void
  • 从有符号字符转换为无符号字符然后再转换回来?

    我正在使用 JNI 并有一个 jbyte 类型的数组 其中 jbyte 表示为有符号字符 即范围从 128 到 127 jbyte 表示图像像素 对于图像处理 我们通常希望像素分量的范围为0到255 因此 我想将jbyte值转换为0到255
  • 如何设置 CMake 与 clang 交叉编译 Windows 上的 ARM 嵌入式系统?

    我正在尝试生成 Ninja makefile 以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C 项目 我为 CMake 创建了一个工具链文件 但似乎存在错误或缺少一些我无法找到的东西 当使用下面的工具链文件调用 CM
  • 启动画面后主窗口出现在其他窗口后面

    我有一个带有启动屏幕的 Windows 窗体应用程序 当我运行该应用程序时 启动屏幕显示正常 消失并加载应用程序的主窗体 但是 当我加载主窗体时 它出现在包含该应用程序的 Windows 资源管理器目录下 这是运行启动画面然后运行主窗体的代
  • 无法使 Polly 超时策略覆盖 HttpClient 默认超时

    我正在使用 Polly 重试策略 并且正如预期的那样 在重试过程中HttpClient达到 100 秒超时 我尝试了几种不同的方法来合并 Polly 超时策略 将超时移至每次重试而不是总计 但 100 秒超时仍然会触发 我读过大约 5 个

随机推荐

  • 在 Cython 中检查 nan

    我正在寻找一种方法来检查 Cython 代码中的 NaN 值 目前 我正在使用 if value value value is NaN else value is not NaN 有一个更好的方法吗 是否可以使用 Numpy 之类的函数is
  • 使用 kotlin 在 android 中获取屏幕截图的最简单方法是什么?

    我有一个 imageView 和几个 textView 我的应用程序允许用户将 textView 拖动到 imageView 的每个坐标上 imageView不是全屏的 该用户想要 换句话说 这个应用程序允许用户向用户图像添加多个标题 并将
  • Py4JError:JVM 中不存在 SparkConf

    我正在运行 pyspark 但有时它可能不稳定 有几次它在执行此命令时崩溃 spark conf SparkConf 并出现以下错误消息 File home user1 spark spark 1 5 1 bin hadoop2 6 pyt
  • 加载 Apple MAP 时的应用程序大小

    我正在努力解决一个看起来很简单的问题 但它使应用程序的运行大小达到 30 35 MB 该应用程序启用了 ARC 这是场景 1 我调用UIViewcontroller从我的方法中 viewController实例是该方法的本地实例 将其推送到
  • 安卓。文本输入布局。切换密码可见性事件侦听器?

    TextInputLayout 中有一个用于输入类型 textPassword 的密码可见性切换按钮 是否有可能捕获切换事件 我找不到任何公共方法 我查看了 TextInputLayout 的源代码以找到切换按钮的视图类型 它的 Check
  • OSError:无法识别图像文件

    我正在尝试在 pytorch 中执行 impelement 代码 但出现以下错误 我的python版本是3 6 我的操作系统是linux ubuntu 16 04 lts 我在 mac os 旁边安装了 linux 我们将使用 torchv
  • 如何使用 React-Query 处理多个查询

    我已经开始使用 React Query 如果我只需要从数据库中的单个集合中获取数据 它会非常有效 但是 我正在努力寻找一种查询多个集合以在单个组件中使用的好方法 一个查询 没问题 const isLoading isError data e
  • CakePHP Twitter 克隆:无法让关注系统工作

    抱歉 标题不具有描述性 但我不知道如何表达它 目前 我正在尝试使用 cakePHP 开发 Twitter 克隆 因为我是网络编程新手 我带了3张桌子 用户 ID 姓名 id是自动生成的id 用户名 推文 id 内容 user id id是自
  • 在终端上显示输出并将最后 10 行添加到日志文件中

    我需要运行一个脚本并将完整内容输出到终端 然后我想从终端输出中获取最后 10 行并将它们放入日志文件中 我尝试过使用 script sh 2 gt 1 tail 10 gt log log但这会停止向终端的输出 利用流程替代bash wit
  • 按列分组的查询结果的行号

    我有一个包含以下列的表 编号 fk id 接收日期 可能有多个记录具有共同的fk id 它代表相关表中的外键id 我需要创建一个查询 为每条记录分配行号 按 fk id 分组 按 rcv date 排序 我最初从以下查询开始 它对于排序和分
  • json_decode() 无法正常工作

    这里我使用简单的html jquery ajax文件 ajax代码在这里 var email email protected cdn cgi l email protection var username ankur 07 var pass
  • Celery Beat:如何定义定义为类的周期性任务(基于类的任务)

    到目前为止 我只处理过定义为函数的 Celery 任务 我曾经定义它们的周期性CELERYBEAT SCHEDULE范围 像这样 from datetime import timedelta CELERYBEAT SCHEDULE add
  • 在 Swift 中实现协议的 NSManagedObject 的 EXC_BAD_ACCESS 错误

    我有以下两种方法 func isAuthenticated gt Bool var currentUser CurrentUser self getCurrentUser if currentUser nil return false se
  • 为什么serverstatus对mongodb写操作有不好的影响?

    我有 1 个 mongos 3 个 mongod 和 3 个配置服务器 当我写一些文档时 有时其中一个 mongods 的插入速度很慢 并且 mongod 日志文件中出现 serverstatus was very Slow 为什么 版本是
  • 如何使用 sqlite3.exe 从导出的 .sql 脚本创建数据库

    尝试将 SqlCe 数据库转换为 SQLite 我将其导出到 sql文件 现在我将如何使用sqlite exe以此创建数据库 sql file 放在哪里sql3 exe file 在 cmd 提示符或在sqlite exe shell 使用
  • Java 数组具有多种数据类型

    我可以使用什么来存储多种不同类型的数据 Int String 等 我有 PHP 背景 我可以将不同类型的数据存储到数组中 但我不知道如何在 Java 中做到这一点 举个例子 array array val1 gt 1 val2 gt cat
  • 是否可以从 PHP 检查 PHP 文件语法?

    我使用自动加载功能动态加载 PHP 类文件 这些文件可能由于某种原因丢失或损坏 自动加载将成功报告丢失的文件 以便应用程序逻辑可以处理该问题 但是 如果这些文件损坏 则整个处理会停止 用户会看到空白屏幕 并且错误日志中会显示 PHP 解析错
  • 尝试获取进程启动时间时“访问被拒绝”

    现在我正在尝试获取计算机上运行的所有进程的启动时间 到目前为止我的代码是这样的 foreach Process item in Process GetProcesses txtActivity AppendText item StartTi
  • 两个自动机之间的等价

    确定两个自动机之间的等价性的最佳或最简单的方法是什么 即 如果给定两个有限自动机 A 和 B 我如何确定两者是否识别相同的语言 它们都是确定性的或都是非确定性的 一种不同的 更简单的方法是对自动机进行补充和交叉 自动机A相当于B iff L
  • 允许同一 COM 库的多个版本

    我编写了一个 C 程序和库 允许用户更轻松地使用特定专有模拟器的 COM 接口 目前 我必须为我希望支持的每个版本的模拟器构建和分发不同版本的 C 库 开发模拟器的公司定期发布新版本 每个新版本都会有一个递增的主版本号 据我所知 版本之间的