Search code examples
c#.netdllcomcom-interop

Making C# Class Library COM-Visible in Visual Studio 2022


My ultimate objective is to build a class library (Calculator.dll) in C#, containing functions that will be made accessible to Excel via VBA.

I had hoped to avoid the need to register the dll, and rather, use the Declare Function statement in the VBA code, but apparently this is not possible and my research has pointed me to needing to make the class library COM-Visible, then register it, and add it as a reference to the VBA project. It seems like this was a matter of clicking a box in a dialog for the project properties in earlier Visual Studio versions, but I don't see the box in VS2022?!

These are the steps I've taken with a "toy" example, and the problems I've encountered.

(1) I built the following .dll with a class Calculate and a simple method to Add two integers. Since we use 32-bit Excel, I configured it to x86.

namespace ClassLibraryCalculator
{
    public class Calculate
    {
        public int Add(int a,int b){ return a + b; }
    }
} 

(2) From the command prompt, running as administrator, I attempted to run regsvr32 "ClassLibraryCalculator.dll" but encountered an error "..was loaded but the entry-point DllRegisterServer was not found"

From searching around, the remedy for this is said to be to modify the project properties, the was (in earlier versions of VS?) a dialog box enter image description here

with a check box, but I see nothing related to COM in Visual Studio 2022 Project Properties.


Solution

  • First make sure you create a project of type "Class library (.NET Framework)" that uses the classic Windows .net Framework like version 4.8. Do not choose the "Class library" project type that is based on .NET Standard and supports multiple different operating systems.

    enter image description here

    After creating the project, open the project properties by right-clicking on the project in the Solution Explorer and selecting "Properties".

    In the project properties, go to "Application", then click on "Assembly Information".

    enter image description here

    In the "Assenmbly Information" dialog, enable the "Make assembly COM-Visible" checkbox.

    enter image description here

    For details see Turn a simple C# DLL into a COM interop component

    Note that you can use the setting "Register for COM interop" on the "Build" area of the project properties to register the DLL (VS needs to run with admin privileges for that). When trying to register from command line, don't use "regsvr32", but "regasm". Be aware that there is a 32bit and a 64bit version of regasm available. Use the correct one.

    Further important hints:

    • If you run Office as 64bit executables, choose "Platform target = x64" in the Build area in the project properties.
    • If you run Office as 32bit executables, choose "Platform target = x86" in the Build area in the project properties.

    Note that "Any CPU" will not work. If you want to support both 32bit and 64bit instances of Office, you need to build two variants of your dll and register both.


    This is the sample class I use for testing:

    using System;
    using System.Runtime.InteropServices;
    
    namespace ClassLibrary4
    {
        [Guid("ECB682F0-8AF1-40EA-B73A-1FACF3C7F742")]
        public interface IClass1
        {
            void Test();
        }
    
        [Guid("4EC93EC5-FA8C-4E82-8931-E47D979BDA93")]
        public class Class1 : IClass1
        {
            public void Test()
            {
                System.Console.Beep();
            }
        }
    }
    

    Note that you cannot use these GUIDs but must use your own ones. Use the "Tools > Create GUID" command in Visual Studio for that.

    Here is how I use the class from VBA after activating the reference:

    ' Declare variable with interface type
    Dim c As ClassLibrary4.IClass1
    ' Create from class type
    Set c = New ClassLibrary4.Class1
    ' Use.
    c.Test