.net - Excel 从两个不同的 AppDomain 调用 .NET 自动化服务器?

标签 .net excel com vsto appdomain

我有一个 Excel 插件(用 C# 编写),其中包含一个静态变量,该变量是单例数据缓存的核心:

static DataCache _instance;

这是通过三个不同的代码路径访问的:

  1. VSTO 功能区栏上的事件处理程序初始化实例,并读取它以在帮助器对话框中显示
  2. RTD 服务器(声明为 [ComVisible] 并实现 IRtdServer 接口(interface)的类)利用 RTD 公式的数据
  3. 一组自动化调用(在声明为 [ComVisible] 的另一个类中实现)也对数据进行操作。这些是通过单击 Excel 工作表上的按钮时调用的 VBA 代码来调用的。

编辑(#3):

根据首次调用这些代码路径的顺序,我发现我的代码在两个单独的 AppDomain 中运行。

来自功能区栏事件处理程序的所有访问都发生在名为“MyPlugIn.vsto”的 AppDomain 中。如果这是对我的 COM 对象的第一次访问,则所有后续调用(包括 RTD 调用)都发生在同一个 AppDomain 中。

但是,如果第一次访问是通过 RTD 接口(interface)进行的,则该调用和所有后续 RTD 调用都发生在名为“DefaultDomain”的 AppDomain 中。 (当加载带有嵌入式 RTD 公式的已保存文档时,会发生这种情况。)通过工具栏初始化和操作 DataCache 的后续调用仍然发生在“MyPlugIn.vsto”AppDomain 中。这意味着 RTD 公式始终运行,就像 DataCache 未初始化一样(因为一个 AppDomain 中设置的静态变量在另一个 AppDomain 中保持未初始化)。

VSTO 初始化时,Excel 或 VSTO 似乎正在创建 AppDomain。在此初始化之前通过 COM 互操作创建的对象位于默认 AppDomain 中,而之后创建的对象则位于 VSTO AppDomain 中。

无论我的 RTD 服务器对象是在哪个 AppDomain 中创建的,如何确保使用相同的 DataCache 实例?

最佳答案

您的静态变量肯定不会在 AppDomain 之间共享,因此考虑到不同的 AppDomain,您所看到的内容符合预期。

我认为它的工作原理是这样的:

VSTO 加载项在其自己的 AppDomain 中运行。如果您的缓存对象(或 RTD 服务器)的 COM 类工厂是从该 AppDomain 中创建的,它将被加载到调用 AppDomain 中。随后访问该 COM 类会发现它已经加载到进程中,并使用现有的实例。

但是,如果第一次激活是由 Excel 本身触发的,例如通过 RTD 调用,.NET 实现的 COM 对象将被加载到进程的默认 AppDomain 中。除非您创建非托管填充程序,否则您无法控制加载过程的这一部分,因为加载发生时“您的代码”并未运行。

我的一些建议:

  1. 为从 .NET 加载项公开的 RTD 调用创建一些包装函数。这样,您可以确保在调用 Excel 的 Application.RTD 进行真正的 RTD 设置之前加载 RTD 类。

  2. 通过用户定义的函数从 RTD 服务器访问实际缓存 - 这样 Excel 就会调用具有真实缓存的 AppDomain,即使它不是 RTD 服务器所在的当前 AppDomain .

  3. 尝试通过 Application.AddIns 获取外接程序对象...有一种方法可以获取实际的外接程序 COM 对象,并使用其上的某些接口(interface)来访问缓存。 ..

  4. 为您的 RTD 服务器创建一个非托管填充程序(在网络上搜索“COM 填充程序向导”)。以某种方式弄清楚如何加载 VSTO AppDomain,然后将 RTD 服务器加载到该 AppDomain 中。

  5. 看看是否有办法将 VSTO 加载项加载到默认 AppDomain 中。我不知道,但也许有一个标志或开关告诉“Microsoft Office Systems 加载程序”(或现在该部分的名称)不要创建隔离的 AppDomain。

  6. 正确答案:使用Excel-Dna (免责声明:我是开发人员)。它支持托管加载项中的功能区、RTD 和 UDF,无需注册,所有内容都会放入您的加载项 AppDomain 中。它是免费的,但需要一些时间和精力来移植您的东西 - RTD 很简单,但如果您使用大量 VSTO 辅助对象来访问功能区和工作表(表格等),您将需要考虑有点。

我希望这能给你一些想法。

--戈弗特--

关于.net - Excel 从两个不同的 AppDomain 调用 .NET 自动化服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3955184/

相关文章:

excel - Access/Excel VBA 失败

python - 从 Python 获取事件 Excel 工作簿的名称

c# - 如何做 RegAsm 使其涵盖 32 位和 64 位?

com - DllRegisterServer的使用

c# - 使用反射 C# 获取 JsonProperty 属性的名称

c# - 如何将控件的属性绑定(bind)到另一个控件的属性?

excel - 怎么隐藏开发者标签

excel - 如何在不打开 Excel 的情况下运行宏

c# - WebBrowser 控件基本授权标题

.net - 使用SPSite构造函数的FileNotFoundException