C# 什么';我的共享外接程序构造函数有什么问题?

C# 什么';我的共享外接程序构造函数有什么问题?,c#,excel,com,add-in,constructor,C#,Excel,Com,Add In,Constructor,各位早上好: 我目前正试图解决从以前的开发人员那里继承的Excel共享外接程序的几个性能问题,基本上我正在试图找到外接程序在Excel中的内部工作方式,这意味着我已经在网上搜索了信息,我的理解是: 在注册表中,LoadBehavior应设置为3 打开事件期间的Excel工作簿应先加载VBA项目中引用的所有加载项 打开文档后,VBA代码应可以使用我的加载项 现在我将Log4Net添加到外接程序中,奇怪的是,我看到了以下行为 在Excel工作簿中的打开事件期间,存在一个全局变量 Public myA

各位早上好:

我目前正试图解决从以前的开发人员那里继承的Excel共享外接程序的几个性能问题,基本上我正在试图找到外接程序在Excel中的内部工作方式,这意味着我已经在网上搜索了信息,我的理解是:

  • 在注册表中,LoadBehavior应设置为3
  • 打开事件期间的Excel工作簿应先加载VBA项目中引用的所有加载项
  • 打开文档后,VBA代码应可以使用我的加载项
  • 现在我将Log4Net添加到外接程序中,奇怪的是,我看到了以下行为

    在Excel工作簿中的打开事件期间,存在一个全局变量

    Public myAddin As Object
    
    Set myAddin = New TradingAddin.TradingAddin
    
    因此,C#类的构造函数被称为

    几秒钟后,再次调用构造函数,并调用Connection、OnDisconnection等的所有IDTExtensibility2方法。。按预期调用

    我认为Excel加载加载项后,VBE代码应该可以使用它,我可以编写如下代码

    Set myAddin = Application.COMAddins.Item("Trading").Object
    
    但它不返回任何内容,并两次调用类的构造函数来销毁保存在C#对象中的任何状态,这些状态在Excel工作簿的生命周期中应该在内存中可用

    更新:

    该平台为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
    
    你会注意到这和你之前发布的有点不同

    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);
    }
    
    因为AddInist不是作为Office.COMAddin传递的,而是我的类的一个实例,所以 尝试分配给对象属性是不正确的,因为该类中不存在该属性

    我也很好奇Excel是如何加载加载项的,我的意思是基于我刚加载Excel时的观察,OnConnection方法没有立即执行,但直到我点击=AvgCost()函数

    有什么想法吗

    我怎么知道有多少 COM对象的实例包括 加载?或者换言之 有可能有一个 COM对象的实例

    你是说COM插件吗?不能将同一COM加载项多次加载到Excel中

    现在我需要找到一个解决问题的方法 从的VBA调用部分 外接程序,表示如何连接 将外接程序实例添加到VBA中的引用 然后从那里调用所有的方法 通过接口暴露 COM对象

    VBA都是后期绑定的,它不像VB6 DLL或.NET程序集那样预编译为DLL。因此,您的所有VBA调用也必须是延迟绑定的。最简单的方法是调用
    Excel.Appliction.Run(“NameOfYourVbaMacro”)
    调用工作簿中标准模块中存储的任何宏。(您可以使用
    Excel.Application.Workbooks[“NameOfYourAddin.xla”]
    按名称访问工作簿。除强制加载外,您无需将其视为外接程序。)您还可以使用反射代码访问工作簿和工作表成员,如果您在
    本工作簿
    类模块或任何
    工作表
    类模块后面有代码

    我认为一旦Excel加载 外接程序应可供用户使用 VBE代码,我可以写一些东西 像

    设置myAddin= Application.COMAddins.Item(“交易”).对象

    因此,如果我理解正确,您不仅希望让您的C#托管COM外接程序调用VBA代码(如上所述),而且现在还希望让VBA代码能够调用我们的C#托管COM外接程序?我认为这是一个复杂的吨,可能需要一些重新思考。。。但这是可以做到的

    通过
    ComAddin.Object
    属性向COM调用方公开托管COM加载项在从C#完成时很棘手,但可行。见以下讨论:

    我希望这能帮你走

    迈克

    编辑:对佩德罗回复的回应

    佩德罗

    你会注意到这看起来有点像 和你贴的不一样 以前

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

    至少,您的最后一行看起来不正确:

    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);
    
    该行看起来应该抛出异常。我很惊讶,事实并非如此。但类似于此的代码——您为希望访问的COM外接程序传入progId——通常由希望通过.Object属性访问COM外接程序的外部调用方使用。这不是应该在外接程序本身中使用的代码

    因为外接程序不是作为 Office.COMAddin只是我的一个例子 类,因此尝试将 对象属性不正确,因为它 在那个类中不存在

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

    如果你想尝试超越标准方法的新奇事物,那没关系,但我会先得到一个简单的例子。尝试复制我在示例中显示的代码。一旦你有了工作,你可以尝试进入更复杂的操作。但是一旦你有了一个简单的版本,我想你会发现这就是你所需要的

    我希望这能帮助佩德罗

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