The COMClient easy integration sample is a simple approach to bypassing the proxygen/proxy layer for COM object models. It was recently improved (see description and helps appended below) These improvements are available in the updated sample for download:
======
COMClient easy integration - using generic COMProxy and VAO
This example shows how simple it is to integrate VSTA into a COM application using a generic proxy and VAO (src included). The generic proxy can be used to expose any COM object model (type library) to VSTA without using proxygen. VAO is used to simplify the integration process, and it implements Non-Destructive Debugging.
Synopsis: The COMClient passes an IUnknown ptr to an instance of its COM object directly to the VSTA Addin via a Connector object:
pConnector->AssignHostObject(pDispMyCOMServer);
The VSTA Addin obtains the same instance of the COM Object as a System.__ComObject.
object obj = this.GetHostObject();
The VSTA Addin uses a reference to the COMInterop assembly (created with tlbimp MSDNCOMServer.dll ) to provide strong type information for the COM Object .
MSDNCOMServerLib.IMyCOMServer myOM = obj as MSDNCOMServerLib.IMyCOMServer;
myOM.MySimpleCOMServerMethod();
This approach uses a generic proxy layer (no need to run proxygen) that exposes one method to the Addin author.
System.Object Connector.GetHostObject()
Although the sample macro does not demonstrate it, this hookup method can easily be hidden in a global property like 'Application' so that the Addin author can use normal syntax to access the Application object model:
Application.MySimpleCOMServerMethod();
==
This sample was recently updated…
Updated with revised VAO source and a revised COMClient sample that properly manages messageloop and the ComConnector ref count:
The change in VAO is in VSTAHookup.cs, StopVSTA() method’s last few lines, which causes the connector object to be released immediately:
[
mHostItemProvider = null;
GC.Collect();
GC.WaitForPendingFinalizers();
]
public void StopVSTA()
{
// Safely exit debug mode in the VSTA IDE before shutting VSTA down
if (mDTE != null)
{
StopDebugging();
mDTE.Quit();
}
try
{
ExternalDebugging.UnregisterExternalDebugHost(mHostDebugUri);
}
catch
{
// Ignore the exception
}
UnloadAppAddIns();
UnloadMacros();
try
{
if (mAddInProcess != null)
{
mAddInProcess.AddInProcessExited -= new EventHandler(AddInProcess_AddInProcessExitedMacro);
mAddInProcess.Dispose();
mAddInProcess = null;
}
}
catch
{
// Ignore the exception
}
mHostItemProvider = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
=============
The other changes – in COMClient.cpp and COMConnector, ConnectorClass.cpp
properly manages the messageloop and the Connector ref count for proper shut down.
=============
Incidentally, if necessary, your COM application can force the CLR to release all its references to interface ptrs inside RCWs (ie: like VSTA’s reference to CLSID_COMConnector instance) by calling CoEEShutDownCOM() as follows:
#include "cor.h"
…
CoEEShutDownCOM();
This was not necessary in the sample, and usually should not be necessary.
Also, your unmanaged application can instruct the CLR to shutdown in an orderly way (includes CLR calling finalization of all unfinalized .NET objects) and exit process by calling CorExitProcess() with passed in error code. This may be needed by pre-VC++7 COM clients to assure that finalization occurs at shutdown as expected:
#include "mscoree.h"
…
CorExitProcess(0);
==========
Posted
Apr 30 2007, 05:20 PM
by
Gary