- Make the server .Net Assembly Com-visible and Com-Compatible
- Register the server assembly in the RunTime Object Table (ROT) so that the client assembly can find it at run time
The technique for exposing a .Net assembly to COM is not too difficult and is covered in a number of locations on the web. The task of registering a COM object in the ROT and retrieving a reference to that COM object from another application is a bit tricky. Here’s some code that I’ve found works for that:
Option Strict On Option Explicit On Imports System.Runtime.InteropServices Imports System.Runtime.InteropServices.ComTypes Imports System.Runtime.InteropServices.Marshal Public Class ROTHook Private Const ROTFLAGS_REGISTRATIONKEEPSALIVE As Integer = 1 Private Const ROTFLAGS_ALLOWANYCLIENT As Integer = 2 <DllImport("ole32.dll", ExactSpelling:=True, PreserveSig:=False)> _ Private Shared Function GetRunningObjectTable(ByVal reserved As Int32) As IRunningObjectTable End Function <DllImport("ole32.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True, PreserveSig:=False)> _ Private Shared Function CreateItemMoniker(ByVal lpszDelim As String, ByVal lpszItem As String) As IMoniker End Function <DllImport("ole32.dll", ExactSpelling:=True, PreserveSig:=False)> _ Private Shared Function CreateBindCtx(ByVal reserved As Integer) As IBindCtx End Function Public Shared Function AddToROT(ByVal obj As Object, ByVal classID As String) As Integer '---------------------------------------------------------------------------------- ' AddToROT ' ' Abstract - Adds a Reference to This Object to the Runtime Object Table ' ' Parameters ' obj Object to register ' classID Class ID of object to register ' ' Return Value cookie to revoke ROT registration '---------------------------------------------------------------------------------- Dim cookieValue As Integer Dim rot As IRunningObjectTable = Nothing Dim moniker As IMoniker = Nothing Try '---- Get the ROT ------------------------------------------------------------- rot = GetRunningObjectTable(0) '--- Create a moniker --------------------------------------------------------- Dim objName As String = "{" + classID + "}" moniker = CreateItemMoniker("!", objName) '--- Registers the object in the running object table ------------------------- cookieValue = rot.Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, obj, moniker) Return cookieValue Catch Exc As Exception Throw Exc Finally '--- Releases the COM objects ----------------------------------------------- If Not (moniker Is Nothing) Then Try While (Marshal.ReleaseComObject(moniker) > 0) End While Catch ex As Exception Exit Try End Try End If If Not (rot Is Nothing) Then Try While (Marshal.ReleaseComObject(rot) > 0) End While Catch ex As Exception Exit Try End Try End If End Try End Function Public Shared Function GetObjectByClassName(ByVal objClassName As String) As Object Return GetActiveObject("!" + objClassName) End Function Public Shared Function GetObjectByClassID(ByVal objClassID As String) As Object Return GetActiveObject("!{" + objClassID + "}") End Function Public Shared Function GetActiveObject(ByVal objName As String) _ As Object '---------------------------------------------------------------------------------- ' GetActiveObject ' ' Abstract - Gets an Instance of this Object from the Runtime Object Table ' ' Parameters ' ' Return Value Object found or Nothing if Not Found '---------------------------------------------------------------------------------- Try Dim ROTObject As Object = Nothing Dim runningObjectTable As IRunningObjectTable Dim monikerEnumerator As IEnumMoniker = Nothing Dim monikers(1) As IMoniker runningObjectTable = GetRunningObjectTable(0) runningObjectTable.EnumRunning(monikerEnumerator) monikerEnumerator.Reset() Dim numFetched As IntPtr = New IntPtr() While (monikerEnumerator.Next(1, monikers, numFetched) = 0) Dim ctx As IBindCtx ctx = CreateBindCtx(0) Dim runningObjectName As String = "" monikers(0).GetDisplayName(ctx, Nothing, runningObjectName) runningObjectName = runningObjectName.ToUpper If (runningObjectName.StartsWith(objName.ToUpper)) Then Dim runningObjectVal As Object = Nothing runningObjectTable.GetObject(monikers(0), runningObjectVal) ROTObject = CType(runningObjectVal, Object) Return ROTObject End If End While Return ROTObject Catch Exc As Exception Throw Exc End Try End Function Public Shared Sub RemoveFromROT(ByVal myCookie As Integer) '---------------------------------------------------------------------------------- ' RemoveFromROT ' ' Abstract - Removes a Reference to This Object From the Runtime Object Table ' ' Parameters ' ' Return Value '---------------------------------------------------------------------------------- If (myCookie = 0) Then Exit Sub Dim rot As IRunningObjectTable = Nothing Try '--- Get the running object table and revoke the cookie ---------------- rot = GetRunningObjectTable(0) rot.Revoke(myCookie) myCookie = 0 Catch Exc As Exception Throw Exc Finally If Not (rot Is Nothing) Then While (Marshal.ReleaseComObject(rot) > 0) End While End If End Try End Sub End Class
You can use the “AddToROT” method to register an object in the ROT by classID – that method will return a cookie that can be used later to remove the object. The “GetObjectByClassID” can be used to retrieve the object from another process.
Chuck

0 comments:
Post a Comment