如何使用C#ITypeLib和ITypeInfo获取DLL或OCX版本信息

时间:2015-09-08 14:36:02

标签: c# dll vb6

在大多数情况下,必须在使用前注册VB6 DLL和OCX。在Visual Basic项目(VBP)文件中,引用的对象列出如下:

Object={70031B70-1070-0D70-AC0E-B049A0701010}#1.0#0; Component.ocx
Reference=*\G{000CD090-0D00-4F07-0707-80040E010704}#1.0#0#..\References\GeneralLibrary.dll#General Purpose Libraries

更新这些文件后,我需要更改VB6项目中的所有引用。由于VBP文件只是文本文件,因此可以使用文本解析更新这些引用。需要注意的是,我需要提前知道每个组件和版本的GUID。

经过一些搜索后,我发现Windows中的oleaut32.dll库可用于从DLL收集信息。这可以通过C#使用ITypeLibITypeInfo来充分利用。

我能够搜索一个使用C#来读取有问题的DLL文件以获取GUID和版本信息的方法。但是,ITypeLibITypeInfo的可用文档没有任何示例。我也无法在网上找到任何例子。

示例代码:

class Program
{
    [DllImport("oleaut32.dll", PreserveSig=false)]
    public static extern ITypeLib LoadTypeLib([In, MarshalAs(UnmanagedType.LPWStr)] string typelib);

    static void Main(string[] args)
    {
        ITypeLib dllLibrary;
        ITypeInfo information;

        dllLibrary = LoadTypeLib("C:\\common_files\\Common.dll");

        dllLibrary.GetTypeInfo(0, out information);
        Console.ReadLine();
    }
}

问题
如何使用ITypeLib和ITypeInfo获取DLL或OCX的GUID和版本信息?

警告:由于我们的系统部署方式以及注册表中有许多旧的DLL工件同名的事实,我想避免注册DLL然后读取从注册表中注册的内容

我也无法找到用于获取版本信息的DLL,如this question中所述。

1 个答案:

答案 0 :(得分:2)

以下代码将在C#中加载tlb - 我没有尝试使用嵌入式tlb的DLL或OCX,但它可能适用于那些。如果没有,你需要从嵌入资源中提取tlb(yay!more PInvoke),然后直接在tlb上运行。这是一个完整的命令行应用程序 - 您可以将其复制并粘贴到新的源文件中,并在命令行上进行编译和测试。

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;

public class TypeLibTest
{
  [DllImport("oleaut32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
  private static extern IntPtr LoadTypeLib(string fileName, out System.Runtime.InteropServices.ComTypes.ITypeLib typeLib);

  public static void Main(string[] args)
  {
    System.Runtime.InteropServices.ComTypes.ITypeLib typeLib = null;
    IntPtr ptr = IntPtr.Zero;
    string file = arg[0];
    try
    {
      LoadTypeLib(file, out typeLib);
      typeLib.GetLibAttr(out ptr);

      var typeAttr = (System.Runtime.InteropServices.ComTypes.TYPELIBATTR) Marshal.PtrToStructure(ptr, typeof(System.Runtime.InteropServices.ComTypes.TYPELIBATTR));
      Console.WriteLine("{0}.{1}", typeAttr.wMajorVerNum, typeAttr.wMinorVerNum);   
    }
    catch (COMException ex)
    {
      Console.WriteLine("Error: " + ex.Message);        
    }
    finally
    {
      if (typeLib != null && ptr != IntPtr.Zero)
      { typeLib.ReleaseTLibAttr(ptr); }
    }
  }
}