我的Shared Add-in构造函数有什么问题?

早上好,研究员们:

我目前正在尝试修复从以前的开发人员inheritance的Excel共享加载项的几个性能问题,基本上我试图find加载项的东西如何在Excel内部工作,这意味着我已经在网上search信息我的理解是:

  1. 在registry中,LoadBehaviour应该设置为3
  2. 打开事件期间的Excel工作簿应该先加载VBA项目中引用的所有加载项
  3. 一旦打开文档,我的加载项就可以被VBA代码使用。

现在我将Log4Net添加到加载项中,好奇的是我看到了下面的行为

在Excel工作簿中的打开事件期间,有一个全局variables

Public myAddin As Object Set myAddin = New TradingAddin.TradingAddin 

因此调用C#类的构造器。

几秒钟后,构造函数被调用一次,所有的IDTExtensibility2方法OnConnection,OnDisconnection等被调用。

我以为,一旦Excel加载加载项,它应该是可用的VBE代码,我可以写类似的东西

 Set myAddin = Application.COMAddins.Item("Trading").Object 

但是它返回Nothing并且调用Class的构造函数两次销毁在Excel工作簿生命期内应该在内存中可用的C#对象内保存的任何状态。

更新:

该平台是Visual Studio 2005 Team Edition,目标应用程序是Excel 2003,并且加载项是共享加载项。 我没有使用VSTO。

我试图在VBA中调用的实际代码是

 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 

同时将registry中的LoadBehaviour更改为2,将加载第一次正确启动所有扩展性事件OnConnection,OnDisconecction和Object类构造函数的加载项,现在我需要find一种方法从VBA的调用部分的Add-这意味着如何将加载项实例连接到VBA中的引用,并从那里调用通过COM对象的接口公开的所有方法?

此外,我再次使用ProcMon进行检查,该加载项被发现并加载Excel按照此链接(非常有用) http://blogs.msdn.com/dvespa/archive/2008/10/15/troubleshooting-outlook-com -addins-using-procmon.aspx 。

任何想法,我们也许指向正确的方向?

我怎么能找出多less个COM对象的实例加载? 或换句话说可能有一个COM对象的单个实例?

TIA,Pedro

给迈克:

我试过你的解决scheme,但是我正在面对未指定的错误(exception从HRESULT:0x80004005(E_FAIL))执行此代码时

 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. 

你会注意到这个和你之前发布的有些不同

 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); } 

因为addInInst不是作为Office.COMAddin传递的,而是我的类的一个实例,所以试图分配给对象属性是不正确的,因为它不存在于该类中

此外,我很好奇如何Excel加载插件,我的意思是基于我的观察,当我刚刚加载Excel的OnConnection方法没有立即执行,但直到我打了= AvgCost()函数? ?

有任何想法吗?

我怎么能找出多less个COM对象的实例加载? 或换句话说可能有一个COM对象的单个实例?

你的意思是COM插件吗? 您不能将多个相同的COM加载项加载到Excel中。

现在我需要从插件的VBA中find调用部分的一种方法,这意味着如何将加载项实例连接到VBA中的引用,以及在那里调用通过COM对象的接口暴露的所有方法? ??

VBA是所有迟到的,它不会像VB6 DLL或.NET程序集一样预先编译成DLL。 因此,你所有的VBA电话也必须迟到。 最简单的方法是调用Excel.Appliction.Run("NameOfYourVbaMacro")来调用工作簿中标准模块中存储的任何macros。 (您可以使用Excel.Application.Workbooks["NameOfYourAddin.xla"]按名称访问工作簿。除了强制加载外,不必将其视为加载项。)您也可以如果代码位于ThisWorkbook类模块或任何Worksheet类模块后面,则使用reflection代码来访问工作簿和工作表成员。

我以为,一旦Excel加载加载项,它应该是可用的VBE代码,我可以写类似的东西

设置myAddin = Application.COMAddins.Item(“Trading”)。Object

所以,如果我理解正确的话,你不仅需要让你的C#托pipe的COM插件调用VBA代码(如上所述),而且现在还希望VBA代码能够调用我们的C#托pipe的COM插件? 我认为这是很复杂的,可能需要一些重新思考…但是可以做到。

通过ComAddin.Object属性将您的托pipe的COM加载项公开给COM调用者,如果从C#中完成,那么ComAddin.Object是非常棘手的,但是可行。 请参阅以下讨论:

从自动化客户端调用托pipe加载项方法 。

我希望这有助于你走…

麦克风

编辑:回应佩德罗的回复

佩德罗,

你会注意到这看起来有点不同于你之前发布的…

是的,你的代码是不同的,这就是为什么它不工作!

至less,你的最后一行看起来不正确:

 VBA.Interaction.CallByName(addIn, "Object", VBA.CallType.Let, this); 

相反,你的代码应该传递给你的类addInInst:

 VBA.Interaction.CallByName(addInInst, "Object", VBA.CallType.Let, this); 

而且我不确定你正在尝试做什么这一行:

 Office.COMAddIn addIn = this.excelApp.COMAddIns.Item(ref addInInst); 

这条线看起来应该抛出一个exception。 我很惊讶,它没有。 但是类似于这个的代码 – 在你想要访问的COM加载项的progId中传递的代码 – 通常由希望通过.Object属性访问你的COM加载项的外部调用者使用。 这不是应该从加载项本身使用的代码。

因为addInInst不是作为Office.COMAddin传递的,而是我的类的一个实例,所以试图分配给对象属性是不正确的,因为它不存在于该类中

我不明白你在这里做什么。 我不知道是否可以传入除了实现IDTExtensibility2的类的实例以外的任何其他对象。 至less,通过使用正确的类和接口属性,您返回的任何类都必须是COM可见类。 但是我认为坚持从OnConnection方法中传递实现IDTExtensibility2的类的标准实践要容易得多。 也就是说,传入你的“this”对象引用。

如果你想尝试超越标准方法的花式东西,没关系,但是我会首先得到一个简单的例子。 尝试复制自动化客户端的示例调用托pipe加载项方法中显示的代码。 一旦你有这个工作,你可以尝试进入更复杂的操作。 但是,一旦你有简单的版本工作,我想你会发现这就是你需要的一切。

我希望这有助于佩德罗,

麦克风