C# – 编写COM服务器 – 映射到方法的属性

我们正在尝试替换最初为VB6应用程序编写的COM服务器

我们无法访问源代码。

出于某种原因,VB6应用程序可以调用我们的构造函数,但它得到:

系统错误&H80004002。 没有这样的接口支持。

我假设它试图获取QueryInterface的接口。

我们通过regasm / tlb和gacutil正确发送了我们的程序集,但后来我发现了一些奇怪的东西。 我打开了为程序集生成的.tlb文件regasm,并注意到我界面上的所有属性都显示为方法。

这是.Net工具正在做什么吗? 这会导致我的问题吗?

以下是原始文件的完整tlb定义:

// Generated .IDL file (by the OLE/COM Object Viewer) // // typelib filename: UtopiaKeyboard.tlb [ uuid(9B4E1840-FF65-11CF-AA2E-0020AFA49D5A), version(1.0), helpstring("OPOS POSKeyboard OLE Control") ] library POSKEYBOARDLib { // TLib : // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046} importlib("STDOLE2.TLB"); // Forward declare all types defined in this typelib dispinterface _DPOSKeyboard; dispinterface _DPOSKeyboardEvents; [ uuid(9B4E1841-FF65-11CF-AA2E-0020AFA49D5A), helpstring("Dispatch interface for OPOS POSKeyboard OLE Control"), hidden ] dispinterface _DPOSKeyboard { properties: [id(0x00000001) ] BSTR CheckHealthText; [id(0x00000002) ] VARIANT_BOOL Claimed; [id(0x00000003) ] VARIANT_BOOL DataEventEnabled; [id(0x00000004) ] VARIANT_BOOL DeviceEnabled; [id(0x00000005) ] VARIANT_BOOL FreezeEvents; [id(0x00000006) ] long ResultCode; [id(0x00000007) ] long ResultCodeExtended; [id(0x00000008) ] long State; [id(0x00000009) ] BSTR ControlObjectDescription; [id(0x0000000a) ] long ControlObjectVersion; [id(0x0000000b) ] BSTR ServiceObjectDescription; [id(0x0000000c) ] long ServiceObjectVersion; [id(0x0000000d) ] BSTR DeviceDescription; [id(0x0000000e) ] BSTR DeviceName; [id(0x0000000f) ] long POSKeyData; [id(0x0000001a) ] VARIANT_BOOL AutoDisable; [id(0x0000001b) ] long BinaryConversion; [id(0x0000001c) ] long DataCount; [id(0x0000001d) ] VARIANT_BOOL CapKeyUp; [id(0x0000001e) ] long EventTypes; [id(0x0000001f) ] long POSKeyEventType; [id(0x00000021) ] long CapPowerReporting; [id(0x00000022) ] long PowerNotify; [id(0x00000023) ] long PowerState; methods: [id(0x00000010)] long Open([in] BSTR DeviceName); [id(0x00000011)] long Close(); [id(0x00000012)] long Claim([in] long Timeout); [id(0x00000013)] long Release(); [id(0x00000014)] long CheckHealth([in] long Level); [id(0x00000015)] long ClearInput(); [id(0x00000016)] long DirectIO( [in] long Command, [in, out] long* pData, [in, out] BSTR* pString); [id(0x00000017)] void SOData([in] long Status); [id(0x00000018)] void SODirectIO( [in] long EventNumber, [in, out] long* pData, [in, out] BSTR* pString); [id(0x00000019)] void SOError( [in] long ResultCode, [in] long ResultCodeExtended, [in] long ErrorLocus, [in, out] long* pErrorResponse); [id(0x00000020)] long SOProcessID(); [id(0x00000024)] void SOStatusUpdate([in] long Status); }; [ uuid(9B4E1842-FF65-11CF-AA2E-0020AFA49D5A), helpstring("Event interface for OPOS POSKeyboard OLE Control") ] dispinterface _DPOSKeyboardEvents { properties: methods: [id(0x00000001)] void DataEvent([in] long Status); [id(0x00000002)] void DirectIOEvent( [in] long EventNumber, [in, out] long* pData, [in, out] BSTR* pString); [id(0x00000003)] void ErrorEvent( [in] long ResultCode, [in] long ResultCodeExtended, [in] long ErrorLocus, [in, out] long* pErrorResponse); [id(0x00000004)] void StatusUpdateEvent([in] long Status); }; [ uuid(9B4E1843-FF65-11CF-AA2E-0020AFA49D5A), helpstring("OPOS POSKeyboard OLE Control"), control ] coclass POSKeyboard { [default] dispinterface _DPOSKeyboard; [default, source] dispinterface _DPOSKeyboardEvents; }; }; 

这是我的.Net程序集的生成tlb:

 // Generated .IDL file (by the OLE/COM Object Viewer) // // typelib filename: POSKEYBOARDLib.tlb [ uuid(9B4E1840-FF65-11CF-AA2E-0020AFA49D5A), version(1.0), custom(90883F05-3D28-11D2-8F17-00A0C9A6186D, "POSKEYBOARDLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5824208931aaf68b") ] library POSKEYBOARDLib { // TLib : // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D} importlib("mscorlib.tlb"); // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046} importlib("STDOLE2.TLB"); // Forward declare all types defined in this typelib dispinterface _DPOSKeyboard; dispinterface _DPOSKeyboardEvents; [ uuid(9B4E1841-FF65-11CF-AA2E-0020AFA49D5A), version(1.0), custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "POSKEYBOARDLib._DPOSKeyboard") ] dispinterface _DPOSKeyboard { properties: methods: [id(0x00000001), propget] BSTR CheckHealthText(); [id(0x00000001), propput] void CheckHealthText([in] BSTR rhs); [id(0x00000002), propget] VARIANT_BOOL Claimed(); [id(0x00000002), propput] void Claimed([in] VARIANT_BOOL rhs); [id(0x00000003), propget] VARIANT_BOOL DataEventEnabled(); [id(0x00000003), propput] void DataEventEnabled([in] VARIANT_BOOL rhs); [id(0x00000004), propget] VARIANT_BOOL DeviceEnabled(); [id(0x00000004), propput] void DeviceEnabled([in] VARIANT_BOOL rhs); [id(0x00000005), propget] VARIANT_BOOL FreezeEvents(); [id(0x00000005), propput] void FreezeEvents([in] VARIANT_BOOL rhs); [id(0x00000006), propget] long ResultCode(); [id(0x00000006), propput] void ResultCode([in] long rhs); [id(0x00000007), propget] long ResultCodeExtended(); [id(0x00000007), propput] void ResultCodeExtended([in] long rhs); [id(0x00000008), propget] long State(); [id(0x00000008), propput] void State([in] long rhs); [id(0x00000009), propget] BSTR ControlObjectDescription(); [id(0x00000009), propput] void ControlObjectDescription([in] BSTR rhs); [id(0x0000000a), propget] long ControlObjectVersion(); [id(0x0000000a), propput] void ControlObjectVersion([in] long rhs); [id(0x0000000b), propget] BSTR ServiceObjectDescription(); [id(0x0000000b), propput] void ServiceObjectDescription([in] BSTR rhs); [id(0x0000000c), propget] long ServiceObjectVersion(); [id(0x0000000c), propput] void ServiceObjectVersion([in] long rhs); [id(0x0000000d), propget] BSTR DeviceDescription(); [id(0x0000000d), propput] void DeviceDescription([in] BSTR rhs); [id(0x0000000e), propget] BSTR DeviceName(); [id(0x0000000e), propput] void DeviceName([in] BSTR rhs); [id(0x0000000f), propget] long POSKeyData(); [id(0x0000000f), propput] void POSKeyData([in] long rhs); [id(0x00000010)] long Open([in] BSTR DeviceName); [id(0x00000011)] long Close(); [id(0x00000012)] long Claim([in] long Timeout); [id(0x00000013)] long Release(); [id(0x00000014)] long CheckHealth([in] long Level); [id(0x00000015)] long ClearInput(); [id(0x00000016)] long DirectIO( [in] long Command, [in, out] long* pData, [in, out] BSTR* pString); [id(0x00000017)] void SOData([in] long Status); [id(0x00000018)] void SODirectIO( [in] long EventNumber, [in, out] long* pData, [in, out] BSTR* pString); [id(0x00000019)] void SOError( [in] long ResultCode, [in] long ResultCodeExtended, [in] long ErrorLocus, [in, out] long* pErrorResponse); [id(0x0000001a), propget] VARIANT_BOOL AutoDisable(); [id(0x0000001a), propput] void AutoDisable([in] VARIANT_BOOL rhs); [id(0x0000001b), propget] long BinaryConversion(); [id(0x0000001b), propput] void BinaryConversion([in] long rhs); [id(0x0000001c), propget] long DataCount(); [id(0x0000001c), propput] void DataCount([in] long rhs); [id(0x0000001d), propget] VARIANT_BOOL CapKeyUp(); [id(0x0000001d), propput] void CapKeyUp([in] VARIANT_BOOL rhs); [id(0x0000001e), propget] long EventTypes(); [id(0x0000001e), propput] void EventTypes([in] long rhs); [id(0x0000001f), propget] long POSKeyEventType(); [id(0x0000001f), propput] void POSKeyEventType([in] long rhs); [id(0x00000020)] long SOProcessID(); [id(0x00000021), propget] long CapPowerReporting(); [id(0x00000021), propput] void CapPowerReporting([in] long rhs); [id(0x00000022), propget] long PowerNotify(); [id(0x00000022), propput] void PowerNotify([in] long rhs); [id(0x00000023), propget] long PowerState(); [id(0x00000023), propput] void PowerState([in] long rhs); [id(0x00000024)] void SOStatusUpdate([in] long Status); }; [ uuid(9B4E1842-FF65-11CF-AA2E-0020AFA49D5A), version(1.0), custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "POSKEYBOARDLib._DPOSKeyboardEvents") ] dispinterface _DPOSKeyboardEvents { properties: methods: [id(0x00000001)] void DataEvent([in] long Status); [id(0x00000002)] void DirectIOEvent( [in] long EventNumber, [in, out] long* pData, [in, out] BSTR* pString); [id(0x00000003)] void ErrorEvent( [in] long ResultCode, [in] long ResultCodeExtended, [in] long ErrorLocus, [in, out] long* pErrorResponse); [id(0x00000004)] void StatusUpdateEvent([in] long Status); }; [ uuid(9B4E1843-FF65-11CF-AA2E-0020AFA49D5A), version(1.0), custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "POSKEYBOARDLib.POSKeyboard") ] coclass POSKeyboard { interface _Object; [default] dispinterface _DPOSKeyboard; [default, source] dispinterface _DPOSKeyboardEvents; }; }; 

不知何故,我的属性被列为方法…即使我添加PreserveSig,它仍然会写入2个方法,而不是使它们成为属性。

我应该尝试使其与原始tlb完全相同? 或者至少让它发挥作用。

更新:找到我在事件界面上没有DispIdAttribute的地方。 修复了这个问题,但VB6应用程序仍然失败并出现相同的错误。

您不能拥有名称与IUnknown方法名称重叠的COM接口(QueryInterface,AddRef和Release )。

更新

要让您的C#类生成一个dispinteface(即用于OLE自动化绑定的IDisptach接口),请使用ClassInterfaceAttribute修饰您的类:

 [ClassInterface(ClassInterfaceType.AutoDispatch)] class myClass { public string Foo {get;} public long Bar(); } 

这将生成自动化属性Foo和方法Bar,而不是原始COM接口。

您曾尝试使用链接中包含的信息:
Visual Basic:使用TypeLib信息对象库检查COM组件

[编辑]
看看tlbimp.exe工具是否可以帮到你。

好吧,我想通了……

我在目标应用程序上使用vb6反编译器反编译并导出为vb6项目。

用VS 2008打开它,升级到VB .Net。

运行应用程序并看到错误“无法转换为IOleObject”。

做过谷歌搜索,发现System.Windows.Forms.Control实现了这个接口,所以inheritance自Control修复了我的问题。