You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带[ComSourceInterfaces]属性的C# DLL在VBA WithEvents中无法正常工作

C# COM DLL事件在VBA中调用的问题解决

问题概述

  1. 运行VBA的TestTaskRunner子过程时,执行eventHandler.taskRunner.RunTask "Test Input"报错:Method or data member not found
  2. 不确定C#代码中[ComSourceInterfaces]属性的使用是否正确

问题1:"Method or data member not found" 错误修复

原因

TaskRunner类标记了[ClassInterface(ClassInterfaceType.None)],该设置会阻止.NET自动生成COM可见的类接口,导致VBA无法识别类中的RunTask方法。

修复步骤

  1. 添加COM可见的类接口
    新增ITaskRunner.cs文件,定义类的公共方法接口:

    using System.Runtime.InteropServices;
    
    namespace ComEventTest
    {
        [ComVisible(true)]
        [Guid("f2a7b5d0-1c3e-4d2f-8a9c-123456789abc")] // 生成新的唯一GUID(可通过VS工具生成)
        [InterfaceType(ComInterfaceType.InterfaceIsDual)]
        public interface ITaskRunner
        {
            void RunTask(string input);
        }
    }
    
  2. 让TaskRunner类实现接口
    修改TaskRunner.cs,让类继承ITaskRunner接口,同时优化线程同步避免跨线程问题:

    using System.Runtime.InteropServices;
    using System.Threading.Tasks;
    using System.Threading;
    
    namespace ComEventTest
    {
        [ComVisible(true)]
        [Guid("ac9de195-73e8-44ae-8cf1-d8f110421923")]
        [ClassInterface(ClassInterfaceType.None)]
        [ComSourceInterfaces(typeof(ITaskRunnerEvents))]
        public class TaskRunner : ITaskRunner
        {
            public delegate void TaskCompletedEventHandler(string result);
            public event TaskCompletedEventHandler OnTaskCompleted;
    
            public void RunTask(string input)
            {
                // 获取当前同步上下文,确保事件在VBA主线程触发
                var syncContext = SynchronizationContext.Current;
                Task.Run(async () =>
                {
                    await Task.Delay(5000); // 模拟任务执行
                    syncContext.Post(_ => 
                    {
                        OnTaskCompleted?.Invoke($"Task completed with input: {input}");
                    }, null);
                });
            }
        }
    }
    
  3. 重新注册DLL
    修改代码后,重新注册COM组件:

    • .NET Framework项目:打开管理员命令提示符,执行regasm /codebase ComEventTest.dll
    • .NET Core/.NET 5+:使用对应版本的regasm工具,或通过项目属性启用COM互操作后重新编译

问题2:[ComSourceInterfaces]属性的正确性验证

你的[ComSourceInterfaces(typeof(ITaskRunnerEvents))]使用是正确的,完全符合COM事件暴露的规范:

  • ITaskRunnerEvents标记了[ComVisible(true)]和[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)],满足COM事件接口要求
  • 类中的TaskCompletedEventHandler委托签名与ITaskRunnerEvents中的OnTaskCompleted方法签名完全匹配
  • 事件名称OnTaskCompleted与接口方法名一致,符合COM事件的命名惯例

VBA代码验证

修改C#代码并重新注册后,原VBA代码无需修改即可正常运行:

  • TaskRunnerEventHandler类中的WithEvents变量能正确捕获OnTaskCompleted事件
  • RunTask方法可被VBA正常调用,任务完成后会弹出包含结果的消息框

内容的提问来源于stack exchange,提问作者Adrijano Toys Shop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:54:53