Search This Blog

Showing posts with label template. Show all posts
Showing posts with label template. Show all posts

Monday, May 7, 2012

Example of a COM Dll developed in VB.NET with the COM template

You can find here the code. It is a VS2008 solution file. Just use the .vb classes if you don't have VS2008 to open up the solution

I have already shown in my previous post how to create COM interop assembly in VB.NET and in C#.

You can have a look here and here. For More more detailed info please look also here
where you will find plenty of details on the how COM dll development and deployment works.

I will try to summarize some important point relevant to the VB.NET developer using the COM template here

1) The COM template automatically ticks for you
    Compile / Register for COM interop
    Application / Assembly Infomation... / Make assembly COM Visible
   
The second option is actually a bed idea, becuase it will register for COM all the types you declare in the assembly. If you have some assembly without the GUID it will create them for you generating a registry bloat.
So each time you add a COM Template, go and untick Make assembly COM-Visible.
Once you have done that you need to add as class attributes. (see the code)

2) If you define a Default Property, this will become a default property for your COM object as well. You can also have indexed properties. The ComClassAttribute will associate to it a DispId(0)

3) if you define a GeEnumerator() function that return a IEnumerator than you will enable the For Each ... Next
    loop in VBA. ComClassAttribute will associate to it a DispId(-4)

Public Function GetEnumerator() As System.Collections.IEnumerator Implements              System.Collections.IEnumerable.GetEnumerator
End Function

4) Also public events are exposed.


The code will show you how to create a Collection with a default property and the For Each ... Next loop enabled and how to expose and event.

Employee Class

Imports System.Runtime.InteropServices

<ComClass(Employee.ClassId, Employee.InterfaceId, Employee.EventsId), _
 ComVisible(True)> _
Public Class Employee

#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "dd3ef2f6-261f-477d-af54-10abc39a07d9"
    Public Const InterfaceId As String = "a0680708-b5ca-4679-8e8e-1b012479b8ee"
    Public Const EventsId As String = "d7361527-7a80-4e47-9aff-4e603a26812b"
#End Region

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Public Sub New()
        MyBase.New()
    End Sub

    Private _Name As String
    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            _Name = value
        End Set
    End Property
End Class 
 


 
Employer Class

Imports System.Runtime.InteropServices

<ComClass(Employer.ClassId, Employer.InterfaceId, Employer.EventsId), _
ComVisible(True)> _
Public Class Employer

#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "a0513ce8-fac4-4187-8190-0584f59cda1e"
    Public Const InterfaceId As String = "2c55f846-2dc9-4f0f-9b82-5e16dfefee52"
    Public Const EventsId As String = "2f99d8e4-afe8-46ef-a4e0-d62b4db18a4d"
#End Region

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Public Sub New()
        MyBase.New()
    End Sub

    Public Event OnNameChange(ByRef newName As String)

    Private _Name As String
    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            RaiseEvent OnNameChange(value)
            _Name = value

        End Set
    End Property

End Class

Collection Class


Imports System.Runtime.InteropServices


<ComClass(MyCol.ClassId, MyCol.InterfaceId, MyCol.EventsId), _
ComVisible(True)> _
Public Class MyCol
    Implements IEnumerable

#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "994ba5ce-1301-455b-9334-409e28aea0c3"
    Public Const InterfaceId As String = "87280e58-8be8-40f8-8987-d3fac317c6c3"
    Public Const EventsId As String = "11d12ead-4562-4ab1-a04b-5ef7fa9fba4c"
#End Region

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Dim _SortedList As SortedList
    Public Sub New()
        MyBase.New()
        _SortedList = New SortedList
    End Sub

    Default Public Property Item(ByVal key As Object)
        Get
            Return _SortedList(key)
        End Get
        Set(ByVal value)
            _SortedList(key) = value

        End Set
    End Property

    Public ReadOnly Property Count()
        Get
            Return _SortedList.Count
        End Get
    End Property


    Public Sub Remove(ByVal key As Object)
        _SortedList.Remove(key)
    End Sub


    Public Sub Add(ByVal key As Object, ByVal value As Object)
        _SortedList.Add(key, value)
    End Sub


    Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        'Return _SortedList.GetEnumerator()
        Dim keys As ICollection = _SortedList.Keys
        Return CType(keys.GetEnumerator, IEnumerator)
    End Function
End Class



VBA Code to test the class


Option Explicit
Dim WithEvents a As TestCOMVisible01.Employer


Sub prova()
If a Is Nothing Then
   Set a = New TestCOMVisible01.Employer
End If
a.Name = "Gino"

Debug.Print a.Name

Dim emp1 As New TestCOMVisible01.Employee
Dim emp2 As New TestCOMVisible01.Employee
Dim col As New TestCOMVisible01.MyCol

emp1.Name = "mario"
emp2.Name = "pluto"
Call col.Add("1", emp1)
Call col.Add("2", emp2)

Dim key As Variant
For Each key In col
 Debug.Print col(key).Name
 Next




End Sub

Private Sub a_OnNameChange(newName As String)
   newName = "ho cambiato il nome"
End Sub

Developing a COM Class Collection using VB.NET COM Template

You can find the code here

In this post I will show you how to develop a COM Class Collection in VB.NET using the COM Template.
It is actually very easy, much easier that doing it manually. Here you can see the manual procedure.

The VB.NET ComClassAttribute, used by the COM Class template will generate for you automatically all the interface that you need to be exposed to COM.


If you define a Default indexed property, it will make it the default property for the COM Object, i.e. it will associate a DispId(0) to the Default indexed property.

In addition if you define a function

Function GetEnumerator() as System.Collection.IEnumerator
End Function

it will mark it as DispId(-4) to make it usable for the VB6/VBA For Each ... Next loop.

The COM Add-in will also create for you all the necessary GUID.

As you create a COM Class using the template, the template automatically will tick for you
1) Register for COM interop in Project Property/Compile/Register for COM Interop
2) It will make the assembly COM Visible. It will tick Project Property/Application/Assembly Infomatin/Make Assemby COM Visible.

The second part is usually a bad idea, this is because every type you include in the libray will be exported to COM. In case you do not provide some GUID for the type, each time you build the assembly the project will create some new ones for you, thus creating a dll hell.

The best thing you can do is to Untick Make Assembly COM Visible (and do it every time you use the COM template) and add a attribute ComVisible(true) on top of the class.
See an exampe here



Imports System.Collections
Imports System.Runtime.InteropServices



<ComClass(Employees.ClassId, Employees.InterfaceId, Employees.EventsId)> _
Public Class Employees
    Implements System.Collections.IEnumerable

#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "4999e186-4ea8-4ce1-8da4-12db6f8600e8"
    Public Const InterfaceId As String = "43ecbe2f-714b-4dc9-a76c-85a84320b66d"
    Public Const EventsId As String = "069d7776-4953-44c2-bd17-0ff75cb5748b"#End Region

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Dim _SortedList As SortedList
    Public Sub New()
        MyBase.New()
        _SortedList = New SortedList
    End Sub

    Default Public Property Item(ByVal key As Object)
        Get
            Return _SortedList(key)
        End Get
        Set(ByVal value)
            _SortedList(key) = value

        End Set
    End Property

    Public ReadOnly Property Count()
        Get
            Return _SortedList.Count
        End Get
    End Property


    Public Sub Remove(ByVal key As Object)
        _SortedList.Remove(key)
    End Sub


    Public Sub Add(ByVal key As Object, ByVal value As Object)
        _SortedList.Add(key, value)
    End Sub


    Public Function GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
        'Return _SortedList.GetEnumerator()
        Dim keys As ICollection = _SortedList.Keys
        Return CType(keys.GetEnumerator, IEnumerator)
    End FunctionEnd Class

Thursday, May 20, 2010

Developing COM exposed classes in C#

Press  here to download the template. CSharp_Com_Class.zip will be downloaded.
For some code example see this  post

Here you can find a series of notes I took as reminders to develpod a COM Class in C#.

I will put it here just as a reference, I hope I will have more time in the future to show you a full example.
You can also find here a C# template you can use to start develop C# COM exposed class. You can delete all the comments out of it. I just add them there for my reference.



To install the template in your VS2008 you need first to find out where they are stored.
To do this, go to File, Export Template. After a few click you should find out where your exported templates
are stored
On my PC for example, they are store here
C:\Users\PP\Documents\Visual Studio 2008\My Exported Templates\WFA01.zip

Once you know this path, just copy the CSharp_Com_Class.zip in the following directory.
You must copy the .zip file. Do not unzip them.

C:\Users\PP\Documents\Visual Studio 2008\Templates\ItemTemplates\Visual C#.

If things go well (and it took me sometime to figure out how to do it) you should have a new template in your
Add New Item, Visual C# Item