.NET 8 ComVisible对象通过CreateObject()创建时出现‘Object required’错误
VB6后期绑定调用.NET 8 COM对象时“Object required”错误的解决
问题场景
用.NET 8和C#创建了一个COM可见的计数器类,代码如下:
SimpleCounter.cs
using System.Runtime.InteropServices; namespace Counters { [ComVisible(true)] [Guid("01FB5599-3CD1-462E-98AA-C29614C0AFEC")] [ClassInterface(ClassInterfaceType.None)] [ProgId("Counters.SimpleCounter")] public class SimpleCounter : ISimpleCounter { private int _counter; public SimpleCounter() { _counter = 0; } public int Counter { get { return _counter; } set { _counter = value; } } public void IncrementCounter() { _counter++; } } }
ISimpleCounter.cs(初始版本)
using System.Runtime.InteropServices; namespace Counters { [ComVisible(true)] [Guid("D65B22DD-4E59-4C11-88B3-67A2535D472E")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ISimpleCounter { public int Counter { get; set; } public void IncrementCounter(); } }
Counters.csproj
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net8.0-windows</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> <PlatformTarget>x86</PlatformTarget> <EnableComHosting>true</EnableComHosting> <Platforms>AnyCPU;x86</Platforms> </PropertyGroup> </Project>
项目构建后生成Counters.dll和Counters.comhost.dll,通过dscom32生成并注册TLB,再用regsvr32注册comhost.dll,操作符合.NET 8 COM规范。
在VB6中测试时,早期绑定(直接声明类型)可以正常运行:
Private Sub Command1_Click() Dim obj As New Counters.SimpleCounter MsgBox "Counter is " & obj.Counter obj.IncrementCounter MsgBox "Counter now is " & obj.Counter End Sub
但使用后期绑定(CreateObject)创建对象时,即使obj不为Nothing,调用obj.Counter仍会触发“Object required”错误:
' 报错的代码示例 Private Sub Command1_Click() Dim obj As Object Set obj = CreateObject("Counters.SimpleCounter") MsgBox "Counter is " & obj.Counter ' 此处触发错误 End Sub
原因分析
VB6的后期绑定依赖IDispatch接口来动态解析对象的属性和方法。当接口标记为InterfaceType(ComInterfaceType.InterfaceIsIUnknown)时,.NET仅向COM暴露IUnknown接口,不提供IDispatch支持,导致后期绑定无法识别Counter属性和IncrementCounter方法,从而抛出错误。
而InterfaceType(ComInterfaceType.InterfaceIsDual)会让接口同时暴露IUnknown和IDispatch,既支持早期绑定,也兼容VB6的后期绑定机制。
解决方法
将接口的InterfaceType属性修改为ComInterfaceType.InterfaceIsDual即可解决问题:
修改后的ISimpleCounter.cs
using System.Runtime.InteropServices; namespace Counters { [ComVisible(true)] [Guid("D65B22DD-4E59-4C11-88B3-67A2535D472E")] [InterfaceType(ComInterfaceType.InterfaceIsDual)] public interface ISimpleCounter { public int Counter { get; set; } public void IncrementCounter(); } }
重新构建并注册COM对象后,使用CreateObject的后期绑定代码即可正常运行。
内容的提问来源于stack exchange,提问作者Étienne Laneville
相关产品推荐
相关产品推荐

