Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/265.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 允许同一COM库的多个版本_C#_Com_Interop_Tlbimp - Fatal编程技术网

C# 允许同一COM库的多个版本

C# 允许同一COM库的多个版本,c#,com,interop,tlbimp,C#,Com,Interop,Tlbimp,我编写了一个C#程序和库,允许用户更轻松地使用特定专有模拟器的COM接口 目前,我必须为我希望支持的每个模拟器版本构建和分发不同版本的C#库。开发模拟器的公司定期发布新版本,每个新版本的主版本号都会增加。据我所知,版本之间的COM接口没有变化,所以从我的角度来看,调用和行为都是一样的。但是,如果我根据模拟器版本9.0构建库和安装程序,并且用户安装了版本10.0,那么我的C#程序无法找到模拟器的COM接口。(即使是对模拟器的小升级也会导致COM接口的大版本升级。)因此,我必须针对每个受支持的模拟器

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

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

看来一定有办法做到这一点。我认为本页可能会描述以下方法:。但它似乎对我不起作用

当然,很可能是我做得不对。我按照说明为两个版本的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定义,而忽略类型库和组件类。用户必须使用ActivatorAPI从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;
    }
}

你跟错人说话了。与软件供应商联系,解释他们的更新给您带来的痛苦。也许他们会致力于保持向后兼容性,也许他们会告诉你每次更新都必须重新测试你的应用程序。这当然是真的。你得到了一个否定的答案,也许你会得到一个肯定的答案。那么,上述问题是不可能的吗?我已经联系了供应商,他们向我发送了通过注册表查找最新版本的说明,这并不是真正的问题。他们还声称,为了在同一系统上允许多个版本的模拟器,他们增加了这个数字。(这很常见。)如果不可能,为什么?是因为主要版本的碰撞吗?或者,这是可能的VisualBasic或C++,但不C由于互操作的东西?