【问题标题】:Create a loader stub for OutlookAddInBase为 OutlookAddInBase 创建加载程序存根
【发布时间】:2016-10-03 22:03:06
【问题描述】:

我正在尝试创建一个 Outlook 2013 插件,它将从指定位置加载其他托管插件。基本上是一个加载程序存根,它知道如何找到这些其他插件、加载它们的程序集并注册。

这是一个简单的概念证明:

using System;
using System.Linq;
using System.Windows.Forms;
using System.ComponentModel;
using System.Reflection;
using Microsoft.Office.Tools;
using Microsoft.Office.Core;
using Microsoft.Office.Tools.Ribbon;

[Microsoft.VisualStudio.Tools.Applications.Runtime.StartupObject(0)]
public class TestAddin : IAddInExtension, IExtension, EntryPoint, ISupportInitialize, IComponent, IDisposable, IBindableComponent
{
    private List<EntryPoint> entrypoints = new List<EntryPoint>();
    public TestAddin(Factory factory, IServiceProvider serviceProvider)
    {
        Assembly asm = LoadAddinAssembly();
        foreach (var type in asm.GetTypes())
        {
            var attr = type.GetCustomAttributes(false).OfType<Microsoft.VisualStudio.Tools.Application.Runtime.StartupObjectAttribute>().FirstOrDefault();
            if (attr != null)
            {
                var ep = Activator.CreateInstance(
                    type, factory, serviceProvider)
                    as Microsoft.Office.Tools.EntryPoint;
                if (ep != null)
                {
                    entrypoints.Add(ep);
                }
            }
        }
    }

    public void BeginInit()
    {
        foreach (var inst in entrypoints)
            inst.BeginInit();
    }

    // Implement the rest of the interface methods similar to BeginInit above
}

Outlook 构建我的类,我的类加载另一个插件程序集并创建入口点,然后 Outlook 调用以下 3 个直通方法,然后我调用其他插件:

  • 初始化()
  • 初始化数据绑定()
  • 完成初始化()
  • 它们都不会产生任何错误,但在那之后,任何传递方法都不会被调用,而且我尝试加载的插件也不会做任何事情。

    我需要通过的向 Outlook 公开的官方插件是什么?或者甚至有可能做这样的事情?

    【问题讨论】:

      标签: c# .net outlook office-interop outlook-addin


      【解决方案1】:

      似乎父服务提供者跟踪它创建的每个入口点。如果你像这样抓住 IHostItemProvider:

      serviceProvider.GetService(typeof(IHostItemProvider))
      

      您可以使用反射设置“_entryPoints”(即EntryPoint[])来修改入口点列表。然后调用代码会将它们视为普通的入口点,无需在本地跟踪它们以进行直通调用。

      另一个关键细节是 _entryPoints[0] 似乎是唯一可以注册 UI 某些方面的,因此最好从 OutlookAddInBase 派生(因为它实现了 UI 初始化逻辑)并对CreateRibbonExtensibilityObject() 和 CreateRibbonObjects() 的第一个入口点。

      此外,必须在清单中定义 Ribbons 和 FormRegions,我还没有找到任何解决方法,因此还需要创建一堆通过反射连接起来的直通存根。

      相当脆弱的解决方案,但它现在似乎可以工作(直到微软改变内部结构)。由于 _entryPoints[0] 如此重要,看起来每个加载程序存根只能加载一个插件。

      【讨论】:

        【解决方案2】:

        如果这些其他加载项未加载,您可以通过 Application.COMAddIns 集合加载。获取要加载的加载项的 COMAddIn 对象并设置 COMAddIn.Connect = True。

        另请参阅此处以了解调用另一个加载项的方法的受支持方式:

        https://blogs.msdn.microsoft.com/andreww/2007/01/15/vsto-add-ins-comaddins-and-requestcomaddinautomationservice/

        【讨论】:

        • 感谢您的信息。乍一看,它似乎有一些相关性,但现在我通读了这篇文章,结果发现它与我想要完成的目标完全无关。
        • COMAddins 是一种告诉 Outlook 加载已注册插件的方法。我试图通过在我已经加载和注册的插件中加载程序集来加载插件而不注册它。我希望能够控制在运行时加载哪个版本的外部插件。
        • 您能否阐明“外部插件”的含义以及它与当前加载的插件有何不同?这与引用的程序集有何不同?也许使用反射可能是一种选择?
        • 加载程序存根不包含任何业务逻辑,它的存在只是为了加载另一个插件。此其他插件是外部的,未注册到 Outlook。根据某些数据库键,我想动态加载所需插件的不同版本。我发布的答案解释了所涉及的一些内容,但它有一些问题。我希望您发布的链接可能是这样做的官方方式。
        猜你喜欢
        • 2011-11-30
        • 2016-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-03-29
        • 1970-01-01
        • 2017-02-01
        • 1970-01-01
        相关资源
        最近更新 更多