允许同一个COM库的多个版本 [英] Allowing multiple versions of the same COM library

查看:195
本文介绍了允许同一个COM库的多个版本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I wrote a C# program and library that allow a user to more easily use a particular proprietary simulator's COM interface.

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

Currently I have to build and distribute a different version of the C# library for each version of the simulator I wish to support. The company that develops the simulator regularly releases new versions, and each new version gets an incremented major version number. As far as I can tell, there is no change to the COM interface between versions (yet) so the calls and behavior are all the same from my perspective. However, if I build my library and installer against simulator version 9.0, and a user has version 10.0 installed, my C# program cannot find the simulator's COM interface. (Even minor upgrades to the simulator result in a major version bump to the COM interface.) So I have to build my library against every supported version of the simulator. That's annoying, I would rather distribute a single library that correctly finds and links to the newest simulator at install time.

似乎必须有一种方法来做到这一点。我认为这个页面可能描述的方法:如何:包装多个版本的类型库。但它似乎并不适用于我。

It seems there must be a way to do this. I thought this page might describe the method:How to: Wrap Multiple Versions of Type Libraries. But it didn't seem to work for me.

当然,我可能没有正确地做。我按照方向得到两个版本的COM接口的.il文件。 9.0和10.0。但是我对下一步感到困惑,并且找不到一个例子:

Of course, it's likely I just didn't do it correctly. I followed the directions to get .il files for two versions of the COM interface. 9.0 and 10.0. But I was confused about the next step and couldn't find an example:


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

Using a text editor, insert a second PrimaryInteropAssemblyAttribute attribute below the attribute added by Tlbimp.exe. Include the major and minor version numbers that represent the second type library version.

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

I wasn't sure if I should duplicate the assembly block, or just the line inside the block (which has no version information I can see.) So I duplicated the assembly block like this:

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

这没有效果,但我看不到我的其他解释是否可能。任何人都可以看到我做错了什么?

This didn't work, but I can't see how my other interpretation would even be possible. Can anyone see what I'm doing wrong? Am I on completely the wrong track, or did I just combine the wrong parts of the .il file?

推荐答案

我们解决了这个问题通过不使用 tlbimp.exe 并提供自定义封装器,我们的产品的问题。

We solve this problem for our product by not using tlbimp.exe and providing custom wrappers.

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

Our wrappers provide .NET definitions only for interfaces, ignoring type libraries and component classes. The user must use the Activator API to obtain instances from ProgIDs, which can, of course, become a configuration parameter for his application.

这是可管理的,因为接口是不可变的我们必须为每个接口创建一个包装类,即使实现发生变化。

This is manageable because interfaces are immutable therefore we must create a wrapper class only once for each interface, even as implementations evolve.

示例wrapper:

[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;
    }
}

这篇关于允许同一个COM库的多个版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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