Marc Vitalis
Marc Vitalis

Reputation: 2249

Referencing Unsigned .NET Assemblies in COM (Visual Basic 6)

Before I dig deeper into the rabbit hole... a quick question...

is it possible?

We have this legacy system created in Visual Basic 6 and we are starting to port it to .NET and we want it to be unsigned. The problem is we have to sign our common libraries each time we have updates. (Common libraries is shared across different products).

Since we can't port everything in an instant, we started porting the server first. Currently we designed the client interfaces to be COM visible so that Visual Basic UIs can invoke them.

Common framework dlls that we have are unsigned which is currently utilized by many projects. But for this product, we need to re-sign them which is too much work to do.

If this is not possible, will there be any other way, like wrapper, or some techniques to workaround this problem?

Thanks.

Upvotes: 2

Views: 132

Answers (1)

kmp
kmp

Reputation: 10865

I think this is going to be tricky because of two things (that I guess you have probably already discovered):

  1. You cannot regasm an unsigned library so that it can be exposed to COM.
  2. You cannot reference an unsigned library from a signed one.

Maybe someone has a better idea but given those two constraints I think the only thing you can do is something nasty with reflection...

Say you have a class in an unsigned library that you want to expose to COM that looks like this:

public class TestClass
{
    public string SaySomething()
    {
        return "Hello";
    }
}

You can reference a signed assembly from an unsigned one so the first step could be to create an interface for just the bits of your classes you wish to expose to COM and put those interfaces in a new assembly that is signed. In our case say we define the interface thus (you can fiddle with the various COM attributes to make it to your liking):

[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ITestClass
{
    string SaySomething();
}

Now reference that new assembly from your original one and change the class definition so that it implements the interface.

public class TestClass : ITestClass

Now, go back to your signed assembly and add a little helper factory that looks like this (it is optional to do this but I think doing this in one place is a good idea):

internal static class ClassFactory
{
    // Depending on how you aer hosting this you can use a relative 
    // path here (maybe) - this gets a bit tricky to sort out and is
    // most likely what will cause problems
    private static readonly Assembly UnsignedAssembly =
        Assembly.LoadFrom(@"C:\...\COMClassLibrary.dll");

    internal static T CreateClass<T>(string typeName)
    {
        return (T)Activator.CreateInstance(UnsignedAssembly.GetType(typeName));
    }
}

The last step would be to create a wrapped up version of your class that you can expose to COM like so:

[ClassInterface(ClassInterfaceType.None)]
[ProgId("MyClasses.TestClass")]
public class TestClassWrapped : ITestClass
{
    private readonly ITestClass _original;

    public TestClassWrapped()
    {
        _original = ClassFactory.CreateClass<ITestClass>(
            "COMClassLibrary.TestClass");
    }

    public string  SaySomething()
    {
        return _original.SaySomething();
    }
}

Now register your signed assembly for COM using regasm and that should do it. Massively tedious but given your constraints it is the only thing I can think of.

Suggested reading:

Upvotes: 3

Related Questions