Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expose dll for COM Interop

I thought I knew how to do this, but obviously not so I'd appreciate some help! I can't get my dll to register so I can instantiate it in a VBS, or elsewhere.

I wrote the following sample class, checked "Make assembly COM Visible", checked "Register for COM Interop", then built it. When I try to instantiate it from VBS I get the "Activex component can't create object" error.

This is the class code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Smurf
{
    public class Pants
    {
        public string Explode(bool Loud)
        {
            string result;
            if (Loud)
                result = "BANG";
            else
                result = "pop";
            return result;
        }
    }
}

...and this is the VBS:

Dim a

Set a = CreateObject("Smurf.Pants")

msgbox("ok")

What else do I need to do?

Thanks :)

[edit]

Forgot to mention, after the first failure I tried REGSVR32 and REGASM - no help!

[/edit]

Note that when I try REGSVR32, I get this message:

The Module "C:...\Smurf.dll" was loaded but the entry-point DllRegisterServer was not found. Make sure that "C:...\Smurf.dll" is a valid DLL or OCX file and then try again.

How helpful is that??

This is the latest version of the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Smurf
{
    [Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
    public interface IPants
    {
        [DispId(1)]
        string Explode(bool Loud);
    }

    [Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA71"),
        InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IPantsEvents
    {
        string Explode(bool Loud);
    }

    [ComVisible(true)]
    [Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"),
        ClassInterface(ClassInterfaceType.None),
        ComSourceInterfaces(typeof(IPantsEvents))]
    public class Pants : IPants
    {
        public Pants() { }

        [ComVisible(true)]
        [ComRegisterFunction()]
        public static void DllRegisterServer(string key) { }
        [ComVisible(true)]
        [ComUnregisterFunction()]
        public static void DllUnregisterServer(string key) { }

        [ComVisible(true)]
        public string Explode(bool Loud)
        {
            string result;
            if (Loud)
                result = "BANG";
            else
                result = "pop";
            return result;
        }
    }
}
like image 999
CompanyDroneFromSector7G Avatar asked Jul 19 '12 22:07

CompanyDroneFromSector7G


People also ask

How do I make my DLL COM visible in C#?

In Project Properties > Application tab > Assembly Information button > check "Make assembly COM-Visible". This makes all public methods in the class COM visible. In Project Properties > Build tab > Set "Platform target" to x86. That's all you need to do to create the DLL.

What is register for COM Interop?

Allows your managed .NET assembly to be accessible from an unmanaged COM library. This option will cause Visual Studio to automatically register your assembly as a COM component in the windows registry when the project is compiled. Registering for COM Interop requires administrator permissions.

Does .NET core support COM Interop?

In . NET Core 3.0, a large portion of this support has been added to . NET Core on Windows. The documentation here explains how the common COM interop technologies work and how you can utilize them to interoperate with your existing COM libraries.


1 Answers

There could be a few different things at play here. First, you'll want to use the regasm tool with the /codebase /tlb switch from an elevated command prompt (assuming Windows Vista, 7 or Windows Server 2008). Something like:

regasm "Path to Smurf.dll" /codebase /tlb

Once you have registered the dll using regasm you should be able to invoke it using VBS, VBA or VB6.

I was able to use early binding and late binding from VBA to call the Explode method. However, when I tried from VBScript I received the "ActiveX can't create object error as you did."

I'm running on Windows 7 64 bit, and I recalled that this can cause problems when compiling to 32 bit dlls and running them on 64 bit operating systems. On a whim, I fired up a command prompt and entered:

C:\Windows\SysWow64\CScript.exe "Path to VBScript"

The result was that the script ran correctly and displayed "Pop" on screen.

Here's the somewhat simplified C# code I used as well as the contents of the VBScript file.

namespace Smurf
{
    [Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")]
    public interface IPants
    {
        string Explode(bool Loud);
    }

    [Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA71"),
     InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    public interface IPantsEvents
    {
        string Explode(bool Loud);
    }

    [ComVisible(true)]
    [Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(IPantsEvents))]
    public class Pants : IPants
    {

        [ComVisible(true)]
        public string Explode(bool Loud)
        {
            string result;
            if (Loud)
                result = "BANG";
            else
                result = "pop";
            return result;
        }
    }
}

VBScript:

Dim x 
Set x = CreateObject("Smurf.Pants")
MsgBox (x.Explode(False))
Set x = Nothing
like image 103
Tim Lentine Avatar answered Sep 28 '22 05:09

Tim Lentine