Good morning, fellows developers:
I'm currently trying to fix several performance issues of an Excel Shared Add-in inherited from a previous developer, basically I'm trying to find how the add-in stuff works internally in Excel, meaning I had searched the net for information an my understanding is:
- In the registry the LoadBehaviour should be set to 3
- The Excel Workbook during the open event should previously load all add-ins referenced in the VBA Project
- Once the document is open my add-in should be available to be used by the VBA code.
Now I add Log4Net to the add-in and curiously enough I had seen the following behaviour
During the Open Event in the Excel Workbook there is a global variable
Public myAddin As Object
Set myAddin = New TradingAddin.TradingAddin
Thus the Contructor of the C# Class is called
after a couple of seconds the constructor is called one more time and all the IDTExtensibility2 methods OnConnection, OnDisconnection, etc.. are called as expected.
I thought that once Excel loads the Add-in it should be available to the VBE Code and i could write something like
Set myAddin = Application.COMAddins.Item("Trading").Object
But it returns Nothing and calling the Constructor of the Class twice destroy any state saved inside the C# Object that should be available in memory during the life of the Excel Workbook.
Update:
The Platform is Visual Studio 2005 Team Edition and the Target Application is Excel 2003 and the Add-in is a Shared Add-in. I'm not using VSTO.
The actual code I was trying to invoke in VBA is
Set addIn = Application.COMAddIns.Item("K2Trading.K2Trading").Connect
Set managedObject3 = addIn.Object <--- This value that I thought was an Instance of the Add-in is equal to Nothing (NULL)
Set addIn = Application.COMAddIns("K2Trading.K2Trading").Connect
Also changing the LoadBehaviour in the registry to 3 from 2 loads the Add-in the first time correctly firing all Extensibility Event OnConnection, OnDisconecction and the Object Class Constructor, now I need to find a way for the invocation part from VBA of the Add-in, meaning how to connect the Add-in instance to a reference in VBA and from there call all the methods exposed through the Interface of the COM Object????
Also I double checked using ProcMon that the Add-in was found and loaded by Excel as per this link (very useful) http://blogs.msdn.com/dvespa/archive/2008/10/15/troubleshooting-outlook-com-addins-using-procmon.aspx .
Any ideas our perhaps pointing into the right direction?
How could I find out how many instances of the COM Object are loaded? or put into another words could be possible to have a single instance of a COM Object?
TIA, Pedro
To Mike:
I tried your solution but I'v been facing Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL)) when executing this code
public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom) { object missing = System.Reflection.Missing.Value;
try
{
if (debug)
{
log.Debug("Connection Mode :" + connectMode);
}
this.excelApp = (Excel.Application)application;
this.addInInstance = addInInst;
Office.COMAddIn addIn = this.excelApp.COMAddIns.Item(ref addInInst);
//addIn.Object = this;
// We connect our Instance of the Add-in to the Arrya of COMAddins of Excel
VBA.Interaction.CallByName(addIn, "Object", VBA.CallType.Let, this);
^
|
The Exception occurs here.
You will noticed this looks a little different from you posted a while ago
public void OnConnection( object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom) { // Direct call fails b/c ".Object" is a late-bound call: // // addInInst.Object = this;
// Reflection fails I believe b/c .Object is a 'let' assigned
// property for reference type, which is very unusual even for
// COM (although legal) and is a foreign concept to .NET. Use
// of the right BindingFlags here *might* work, but I'm not sure:
//
// PropertyInfo propInfo;
// propInfo = addInInst.GetType().GetProperty("Object");
// propInfo.SetValue(addInInst, this, null);
// This works!:
VBA.Interaction.CallByName(addInInst, "Object", VBA.CallType.Let, this);
}
Because addInInst is not pass as a Office.COMAddin but a instance of my class, so trying to assign to the Object Property is incorrect since it doesn't exists in that class
Also I'm curious about how Excel loads the Add-ins, what I mean by that is based on my observation when I just loaded Excel the OnConnection method didn't execute right away, but until I hit the =AvgCost() function ??
Any ideas?