views:

586

answers:

3

I have a VB6 project(windows application) and I have to redevelop a module in the existing VB6 project in C#.net.

The module that I develop in C#.net should be a dll and should contain some windows forms. I was able to successfully call a c# console applicaiton dll from my vb6 project but I am facing issues when i try to call a C# class library with winforms from my VB6 project.

This is what I have done for my Proof Of Concept - This is a class file in my C#.net class library project.

namespace TestDll
{
    public interface IClass1
    {
        void DisplayMessage();
    }


    public class Class1:IClass1
    {              
        void IClass1.DisplayMessage()
        { 
            MessageBox.Show ("Displyaing message");
        }

    }
}

I have a form in the same nemspace and I plan to instantiate Class1 and use its object on the page_load event of the C# winform.

In my VB6 project I want to display the form I have in my C#.net dll. I am calling it by this code -

Private Declare Sub DislayMessage Lib "TestDll.dll" ()

Private Sub Command1_Click() //On button click event of the VB6 windows form
DislayMessage
End Sub

I get an error - "Can't find a DLL entry point in DisplayMessage in TestDll.dll"

I am not sure how to solve this error. I am even skeptical if this is the way a C#.net dll which contains some winforms should be called from a VB6.0 windows applicaiton.

Should I instantiate Class1 in my VB6 code? How do I resolve this error? Is my approach correct? Are there better ways to do this?

TIA.

+2  A: 

The only way to do it is to expose your C# class as a COM object (also called a CCW - COM Callable Wrapper), and create an instance of that COM object in your VB6 code.

This should help you get started:

http://www.bing.com/search?q=C%23+CCW&go=&form=QBRE&qs=n

Brannon
Ok, not the *only* way to do it, but the only *sane* way to do it :-P
Brannon
THanks. It is very helpful.But, I am still curious. Can you tell me what is wrong with the code I have posted above?
Pavanred
C-Pound Guru summed it up nicely.
Brannon
A: 

There some excellent help on msdn here:

http://msdn.microsoft.com/en-us/library/6bw51z5z.aspx

Adrian
A: 

You have to make your class COM-Visible. Here's how I would change your code:

namespace TestDll
{
    [Guid("FB8AB9B9-6986-4130-BD74-4439776D1A3D")]
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    [ComVisible(true)]
    public interface IClass1
    {
        [DispId(50)]
        void DisplayMessage();
    }


   [Guid("74201338-6927-421d-A095-3BE4FD1EF0B4")]
   [ClassInterface(ClassInterfaceType.None)]
   [ComVisible(true)]
   [ProgId("TestDll.Class1")]
    public class Class1:IClass1
    {              
        void IClass1.DisplayMessage()
        { 
            MessageBox.Show ("Displyaing message");
        }

    }
}

Note the [DispId(50)]. You want to specify the dispatch ID for your COM-visible methods, properties, and events. If you don't, the compiler will do it for you and you may end up breaking compatibility every time you compile. The number doesn't matter so much as it doesn't change between compiles.

You might want to check out Building COM Objects in C#. It's a pretty good getting started tutorial.

Some highlights:

Exposing the VC# objects to the COM world requires the following …

* The class must be public
* Properties, methods, and events must be public.
* Properties and methods must be declared on the class interface.
* Events must be declared in the event interface.

Every Interface needs a GUID property set before the interface name. To generate the unique Guid , use the guidgen.exe utility and select the Registry Format.

C-Pound Guru