为OutlookAddInBase创建加载程序存根

时间:2016-06-03 18:23:41

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

我正在尝试创建一个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个passthrough方法,然后我调用另一个插件:

  • 初始化()
  • InitializeDataBindings()
  • FinishInitialization()
  • 他们都没有创建任何错误,但在此之后,没有任何直通方法被调用,而且我正在尝试加载的插件永远不会做任何事情。

    什么是暴露给Outlook的官方插件我需要通过什么?或者甚至可以做这样的事情?

    2 个答案:

    答案 0 :(得分:0)

    看起来父服务提供商会跟踪它创建的每个EntryPoint。如果你像这样抓住IHostItemProvider:

    <?php
    //Kill a sudo session if one exists.
    exec('sudo -k');
    
    //Run sudo without authenticating
    $output = exec('sudo echo "foo"');
    var_dump($output); //string(0) ""
    
    //Provide the password and pipe it into sudo.
    $output = exec('echo "password" | sudo -S echo "foo" 2> /dev/null');
    var_dump($output); //string(3) "foo"
    ?>
    

    你可以使用反射设置&#34; _entryPoints&#34; (这是EntryPoint [])修改入口点列表。然后,调用代码将它们视为普通的EntryPoints,无需在本地跟踪它们以进行直通调用。

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

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

    非常脆弱的解决方案,但它似乎现在有效(直到微软改变内部)。而且由于_entryPoints [0]如此重要,看起来每个加载器存根只能加载一个插件。

    答案 1 :(得分:0)

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

    另请参阅此内容以获得调用另一个加载项的方法的受支持方式:

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