Надстройка Outlook 2010 ведет себя странно, когда почта вызывается из другого офисного клиента - PullRequest
1 голос
/ 30 мая 2011

Мне действительно нужна помощь с этим.

Я написал добавление, которое добавляет некоторый текст в строку темы письма при отправке, оно также устанавливает то же значение в свойстве письма черезPropertyAccessor.Это прекрасно работает, когда электронная почта создается через интерфейс Outlook.

Проблема, с которой я столкнулся, заключается в том, что пользователь работает с Excel и решает отправить электронную таблицу в виде вложения из Excel 2010 -> Файл ->Сохранить и отправить -> пункт «Отправить как вложение».

При этом откроется редактор почты Outlook 2010, как и следовало ожидать, пользователь может указать адрес электронной почты и нажать кнопку отправить как обычно, и сообщение будет отправлено как обычно.Проблема в том, что редактор электронной почты не закрывается после отправки, как вы ожидаете.

Я использую событие Globals.ThisAddIn.Application.ItemSend, чтобы внести изменения в электронную почту.Также при отладке замечаю, что это событие срабатывает пару раз при отправке.Аргумент отмены этого события всегда ложен во время выполнения.

1 Ответ

3 голосов
/ 07 декабря 2011

Наконец-то нашел что-то, что, кажется, работает

Разработка оболочки инспектора для Outlook 2010

В случае, если ссылка не работает, как они могут сделать

Вот обертка

namespace OutlookAddIn
{
// Eventhandler used to correctly clean up resources.
// <param name="id">The unique id of the Inspector instance.</param>
internal delegate void InspectorWrapperClosedEventHandler(Guid id);

// The base class for all inspector wrappers.
internal abstract class InspectorWrapper
{
    // Event notification for the InspectorWrapper.Closed event.
    // This event is raised when an inspector has been closed.

    // The unique ID that identifies an inspector window.
    protected InspectorWrapper(Inspector inspector)
    {
        Id = Guid.NewGuid();
        Inspector = inspector;
        // Register Inspector events here
        ((InspectorEvents_10_Event) Inspector).Close += InspectorClose;
        ((InspectorEvents_10_Event) Inspector).Activate += Activate;
        (Inspector).Deactivate += Deactivate;
        (Inspector).BeforeMaximize += BeforeMaximize;
        (Inspector).BeforeMinimize += BeforeMinimize;
        (Inspector).BeforeMove += BeforeMove;
        (Inspector).BeforeSize += BeforeSize;
        (Inspector).PageChange += PageChange;

        // Initialize is called to give the derived wrappers.
        Initialize();
    }

    public Guid Id { get; private set; }

    // The Outlook Inspector instance.
    public Inspector Inspector { get; private set; }
    public event InspectorWrapperClosedEventHandler Closed;

    // .ctor
    // <param name="inspector">The Outlook Inspector instance that should be handled.</param>

    // Event handler for the Inspector Close event.
    private void InspectorClose()
    {
        // Call the Close Method - the derived classes can implement cleanup code
        // by overriding the Close method.
        Close();

        // Unregister Inspector events.
        ((InspectorEvents_10_Event) Inspector).Close -= InspectorClose;

        // Clean up resources and do a GC.Collect().
        Inspector = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();

        // Raise the Close event.
        if (Closed != null)
        {
            Closed(Id);
        }
    }

    protected virtual void Initialize()
    {}

    // Method is called when another page of the inspector has been selected.
    // <param name="ActivePageName">The active page name by reference.</param>
    protected virtual void PageChange(ref string ActivePageName)
    {}

    // Method is called before the inspector is resized.
    // <param name="Cancel">To prevent resizing, set Cancel to true.</param>
    protected virtual void BeforeSize(ref bool Cancel)
    {}

    // Method is called before the inspector is moved around.
    // <param name="Cancel">To prevent moving, set Cancel to true.</param>
    protected virtual void BeforeMove(ref bool Cancel)
    {}

    // Method is called before the inspector is minimized.
    // <param name="Cancel">To prevent minimizing, set Cancel to true.</param>
    protected virtual void BeforeMinimize(ref bool Cancel)
    {}

    // Method is called before the inspector is maximized.
    // <param name="Cancel">To prevent maximizing, set Cancel to true.</param>
    protected virtual void BeforeMaximize(ref bool Cancel)
    {}

    // Method is called when the inspector is deactivated.
    protected virtual void Deactivate()
    {}

    // Method is called when the inspector is activated.
    protected virtual void Activate()
    {}

    // Derived classes can do a cleanup by overriding this method.
    protected virtual void Close()
    {}


    // This factory method returns a specific InspectorWrapper or null if not handled.
    // <param name=”inspector”>The Outlook Inspector instance.</param>
    // Returns the specific wrapper or null.
    public static InspectorWrapper GetWrapperFor(Inspector inspector)
    {
        // Retrieve the message class by using late binding.
        string messageClass = inspector.CurrentItem.GetType().InvokeMember("MessageClass", BindingFlags.GetProperty,
                                                                           null, inspector.CurrentItem, null);

        // Depending on the message class, you can instantiate a
        // different wrapper explicitly for a given message class by
        // using a switch statement.
        switch (messageClass)
        {
            case "IPM.Contact":
                return new ContactItemWrapper(inspector);
            case "IPM.Journal":
                return new ContactItemWrapper(inspector);
            case "IPM.Note":
                return new MailItemWrapper(inspector);
            case "IPM.Post":
                return new PostItemWrapper(inspector);
            case "IPM.Task":
                return new TaskItemWrapper(inspector);
        }

        // Or, check if the message class begins with a specific fragment.
        if (messageClass.StartsWith("IPM.Contact.X4U"))
        {
            return new X4UContactItemWrapper(inspector);
        }

        // Or, check the interface type of the item.
        if (inspector.CurrentItem is AppointmentItem)
        {
            return new AppointmentItemWrapper(inspector);
        }

        // No wrapper is found.
        return null;
    }
}

// Derive a wrapper for each message class/item type.
}

и вот пример переопределения

internal class MailItemWrapper : InspectorWrapper
{
    // The Object instance behind the Inspector, which is the current item.

    public MailItemWrapper(Inspector inspector)
        : base(inspector)
    {
        // Get the item in the current Inspector.
        Item = (MailItem) Inspector.CurrentItem;

        // Register Item events.
        Item.Open += Item_Open;
        Item.Write += Item_Write;
    }

    public MailItem Item { get; private set; }

    // This method is called when the item is visible and the UI is initialized.
    // <param name="Cancel">When you set this property to true, the Inspector is closed.</param>
    private void Item_Open(ref bool Cancel)
    {
        // TODO: Implement something 
    }

    // This method is called when the item is saved.
    // <param name="Cancel">When set to true, the save operation is cancelled.</param>
    private void Item_Write(ref bool Cancel)
    {
        //TODO: Implement something 
    }

    // The Close method is called when the inspector has been closed.
    // Do your cleanup tasks here.
    // The UI is gone, cannot access it here.
    protected override void Close()
    {
        // Unregister events.
        Item.Write -= Item_Write;
        Item.Open -= Item_Open;

        // Release references to COM objects.
        Item = null;

        // Set item to null to keep a reference in memory of the garbage collector.
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }
}

а вот класс ThisAddin

public partial class ThisAddIn
{
    // Holds a reference to the Application.Inspectors collection.
    // Required to get notifications for NewInspector events.
    private Inspectors _inspectors;

    // A dictionary that holds a reference to the inspectors handled by the add-in.
    private Dictionary<Guid, InspectorWrapper> _wrappedInspectors;

    private void ThisAddInStartup(object sender, EventArgs e)
    {
        _wrappedInspectors = new Dictionary<Guid, InspectorWrapper>();
        _inspectors = Globals.ThisAddIn.Application.Inspectors;
        _inspectors.NewInspector += WrapInspector;

        // Also handle existing Inspectors
        // (for example, double-clicking a .msg file).
        foreach (Inspector inspector in _inspectors)
        {
            WrapInspector(inspector);
        }
    }


    // Wrap an Inspector, if required, and store it in memory to get events of the wrapped Inspector.
    // <param name="inspector">The Outlook Inspector instance.</param>
    private void WrapInspector(Inspector inspector)
    {
        var wrapper = InspectorWrapper.GetWrapperFor(inspector);
        if (wrapper != null)
        {
            // Register the Closed event.
            wrapper.Closed += WrapperClosed;
            // Remember the inspector in memory.
            _wrappedInspectors[wrapper.Id] = wrapper;
        }
    }

    // Method is called when an inspector has been closed.
    // Removes reference from memory.
    // <param name="id">The unique id of the closed inspector</param>
    private void WrapperClosed(Guid id)
    {
        _wrappedInspectors.Remove(id);
    }


    private void ThisAddInShutdown(object sender, EventArgs e)
    {
        // Clean up.
        _wrappedInspectors.Clear();
        _inspectors.NewInspector -= WrapInspector;
        _inspectors = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
    }

    #region VSTO generated code

    /// <summary>
    ///   Required method for Designer support - do not modify
    ///   the contents of this method with the code editor.
    /// </summary>
    private void InternalStartup()
    {
        Startup += ThisAddInStartup;
        Shutdown += ThisAddInShutdown;
    }

    #endregion
}

Там должно быть достаточно, чтобы вывести людей из беды, если связь не работает

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...