Problem Description: I'm working on using COM interop to call a C# asynchronous method from VBA. The class (NewAsyncTaskRunner) is recognized and works fine, but the interface (INewCallback) is not recognized in VBA. Upon checking the registry, I think the interface is not named correctly.I'm using Visual Studio Code for development.
C# Code: NewAsyncTaskRunner.cs
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace NewAsyncCallbackTest
{
[ComVisible(true)]
[Guid("dd9e3e74-f630-4ecc-8b09-e45512da443c")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface INewCallback
{
void OnTaskCompleted(string result);
}
[ComVisible(true)]
[Guid("22222222-2222-2222-2222-222222222222")]
[ClassInterface(ClassInterfaceType.None)]
public class NewAsyncTaskRunner
{
public void RunAsyncTask(string input, INewCallback callback)
{
Task.Run(async () =>
{
await Task.Delay(5000); // 5 seconds delay
string result = $"Task completed with input: {input}";
callback.OnTaskCompleted(result);
});
}
}
}
AssemblyInfo.cs
using System.Runtime.InteropServices;
[assembly: ComVisible(true)]
Project File: NewAsyncCallbackLibrary.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net48</TargetFramework>
<LangVersion>10.0</LangVersion>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>MyKeyFile.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
</Project>
Registered the assembly using:
& "C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe" "C:\Path\To\Your\DLL\NewAsyncCallbackLibrary.dll" /codebase /tlb
Registry Verification:
Interface: Found GUID dd9e3e74-f630-4ecc-8b09-e45512da443c under HKEY_CLASSES_ROOT\Interface, but it only shows numbers and version, not INewCallback.
Class: Found GUID 22222222-2222-2222-2222-222222222222 under HKEY_CLASSES_ROOT\CLSID with NewAsyncTaskRunner correctly named.
Issue: The class NewAsyncTaskRunner is recognized in VBA, but the interface INewCallback is not. The interface appears in the registry without its name.
Any insights or suggestions on what might be wrong with the interface registration and how to fix it would be greatly appreciated. Thank you!
As I explained in comment above I had wrong interface search in registry for NewAsyncCallbackTest.INewCallback instead of INewCallback and I have also used NewAsyncCallbackTest.INewCallback in VBA so I thought I miss INewCallback.
So as @Hans Passant said: nothing wrong with C# Code: NewAsyncTaskRunner.cs. Used attribute InterfaceIsIDispatch. DLL is properly registered.
So the correct approach in VBA:
class module TaskRunnerEventHandler
Option Compare Database
Option Explicit
Implements INewCallback
Private Sub INewCallback_OnTaskCompleted(ByVal result As String)
Debug.Print result
End Sub
Usage module
Option Compare Database
Option Explicit
Dim obj As Object
Dim CallbackHandler As CallbackHandler
Sub StartTask(taskParam As String)
Set CallbackHandler = New CallbackHandler
Set obj = CreateObject("NewAsyncCallbackTest.NewAsyncTaskRunner")
obj.RunAsyncTask taskParam, CallbackHandler
End Sub
Sub TestMultipleTasks()
Dim i As Integer
' Loop ten times to check multiple tasks
For i = 1 To 10
StartTask "Task " & i
Sleep 100
Debug.Print "Task " & i & " is running asynchronously!"
Next i
End Sub
So it works perfect now...