如何修复VS C#调用64位COM抛出类型'System.InvalidCastException'的未处理异常

时间:2017-01-05 16:10:17

标签: c# delphi com

我在Delphi Berlin Update 2下有一个32位和64位编译的COM DLL。在32位和64位VBScript(System \ cscript)中调用COM时完全没有问题。用于64位的exe和用于32位see this post的SysWOW64 \ cscript.exe以获取更多详细信息),如下所示:

set rpm = CreateObject("RPMLib.RadioTracer")
set rpu = CreateObject("RPMLib.Utility")
rpm.SomeMethod();
rpu.SomeMethod();

这意味着我已经成功注册了32位和64位:

regsvr32 RPMLib.dll

delphi编译器将相同的源代码编译为两个版本。所以基本上,32位和64位的GUID是相同的。我已经从_TLB.pas文件

中复制了GUID
LIBID_RPMLib: TGUID = '{D6A7108C-E217-4012-9BAA-E82693CE080C}';
IID_IUtility: TGUID = '{F9372AF6-6DAB-4F3F-B017-73FA147CF563}';
CLASS_Utility: TGUID = '{B1694005-EF15-4ED8-9368-6657C6FE3658}';
IID_IRadioTracer: TGUID = '{0DD935C7-ED78-4ACB-94CE-9981359BBE36}';
CLASS_RadioTracer: TGUID = '{175BB24D-598C-4019-AD29-63FC0A47B11F}';
IID_CallBackFuncs: TGUID = '{05E82013-E197-4C0E-B2C4-504226CC1298}';

我创建了一个C#控制台应用程序(Visual Studio 2015),添加了COM参考并放入代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RPMLib;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var rpu = new Utility();            
            Console.WriteLine(rpu.Author);
            var rpm = new RadioTracer();
            Console.WriteLine(rpm.Author);
            Console.ReadLine();
        }
    }
}

如果目标平台是x86,它可以工作。但是,当我切换到x64时,它会抛出此错误(非常令人惊讶仅在创建RadioTracer类时抛出错误而不是另一个抛出错误,例如Utility类):

  

ConsoleApplication2.exe中发生未处理的“System.InvalidCastException”类型异常   附加信息:无法将“System .__ ComObject”类型的COM对象强制转换为接口类型“RPMLib.RadioTracer”。这个   操作失败,因为QueryInterface调用COM组件   对于IID'{0DD935C7-ED78-4ACB-94CE-9981359BBE36}'的接口   由于以下错误而失败:未指定的错误(来自的异常)   HRESULT:0x80004005(E_FAIL))。

RPMLib.dll基本上导出了两个对象,因此您可以创建 RadioTracer() Utility()

从Delphi源代码我可以看到它们是在进程中创建的:

TAutoObjectFactory.Create(ComServer, TUtility, Class_Utility, ciMultiInstance,
  tmApartment);
TAutoObjectFactory.Create(ComServer, TRadioTracer, Class_RadioTracer,
  ciMultiInstance, tmApartment);

最后,这里有一些截图,任何提示?

enter image description here

enter image description here

enter image description here

这是RadioTracer.cs

// Decompiled with JetBrains decompiler
// Type: RPMLib.RadioTracer
// Assembly: Interop.RPMLib64, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: FDE1BB7D-808A-44B6-BE39-4DB3EFA8395B
// Assembly location: c:\RPMLib_Integration_Tests\TestData\Interop.RPMLib64.dll

using System.Runtime.InteropServices;

namespace RPMLib
{
  [Guid("0DD935C7-ED78-4ACB-94CE-9981359BBE36")]
  [CoClass(typeof (RadioTracerClass))]
  [ComImport]
  public interface RadioTracer : IRadioTracer
  {
  }
}

和Utility.cs

// Decompiled with JetBrains decompiler
// Type: RPMLib.Utility
// Assembly: Interop.RPMLib64, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: FDE1BB7D-808A-44B6-BE39-4DB3EFA8395B
// Assembly location: c:\RPMLib_Integration_Tests\TestData\Interop.RPMLib64.dll

using System.Runtime.InteropServices;

namespace RPMLib
{
  [CoClass(typeof (UtilityClass))]
  [Guid("F9372AF6-6DAB-4F3F-B017-73FA147CF563")]
  [ComImport]
  public interface Utility : IUtility
  {
  }
}

其他实验: 我已经删除了32位注册 regsvr32 / u RPMLib.dll ,但问题仍然存在 我试图将32位和64位 interop.RPMLib.dll 添加到项目引用中,而不是选择COM dll本身,它没有帮助。

0 个答案:

没有答案