0

我正在创建一个 Microsoft Outlook 加载项(Visual Studio 2012、C#、COM 加载项,无 VSTO,Outlook 2010/2013/2016),用户必须能够在其中编写和读取必须映射到/从的各种字段消息离开/进入 Microsoft Exchange 时的 MIME 标头(即来自命名空间 PS_INTERNET_HEADERS 的属性)。

当用户转发消息时,我想将原始消息中的属性复制到转发的消息中。我通过监听事件 Application.ItemLoad 和 MailItem.Forward 来做到这一点,其中复制发生在后者的事件处理程序中。

这在我的开发机器上的 Outlook 2013 版本 15.0.4771.1000 中运行良好,但在虚拟机上运行的 Outlook 2013 版本 15.0.4771.1000 中却不行。在具有 Outlook 2010 的其他虚拟机上,它也不起作用。

问题是,如果我在 Inspectors.NewInspector 的事件处理程序中读取转发消息的属性值,我会意外得到空值。但是,如果我更改主题,保存转发消息的草稿并重新打开它,则属性值符合预期。因此,属性以某种方式发生了变化,但是当我第一次在 NewInspector 的事件处理程序中读取它们时,这并没有反映出来。我做错了什么?

下面是一些展示问题的示例代码。我只包含了我认为证明问题所必需的清理代码。

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace ForwardTest
{
    public class Application
    {
        private readonly Outlook.Application application;
        private readonly HashSet<MailItem> loadedMailItems;

        public Application(Outlook.Application application)
        {
            this.application = application;
            loadedMailItems = new HashSet<MailItem>();
            application.ItemLoad += ItemLoad;
            application.Inspectors.NewInspector += NewInspector;
        }

        private void ItemLoad(object item)
        {
            loadedMailItems.Add(new MailItem((Outlook.MailItem)item));
        }

        private void NewInspector(Outlook.Inspector inspector)
        {
            var mailItem = (Outlook.MailItem)inspector.CurrentItem;
            // Next line unexpectedly shows empty values for some Outlook versions.
            System.Windows.Forms.MessageBox.Show(Properties.Get(mailItem), Properties.FooName);
        }
    }

    public class MailItem
    {
        private readonly Outlook.MailItem mailItem;

        public MailItem(Outlook.MailItem mailItem)
        {
            this.mailItem = mailItem;
            ((Outlook.ItemEvents_10_Event)mailItem).Forward += Forward;
        }

        private void Forward(object forward, ref bool cancel)
        {
            var value = Properties.Get(mailItem);
            Properties.Set((Outlook.MailItem)forward, "FW: " + value);
            Marshal.ReleaseComObject(forward);
        }
    }

    public static class Properties
    {
        public const string FooName = "http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/MMHS-Foo";

        public static string Get(Outlook.MailItem mailItem)
        {
            var propertyAccessor = mailItem.PropertyAccessor;
            var values = (object[])propertyAccessor.GetProperties(new[] { FooName });
            var value = values[0] as string ?? string.Empty;
            Marshal.ReleaseComObject(propertyAccessor);
            return value;
        }

        public static void Set(Outlook.MailItem mailItem, string value)
        {
            var propertyAccessor = mailItem.PropertyAccessor;
            propertyAccessor.SetProperty(FooName, value);
            Marshal.ReleaseComObject(propertyAccessor);
        }
    }
}
4

2 回答 2

0

我不确定丢失的属性,但是如果他们在没有打开检查器的情况下从资源管理器转发项目怎么办?

于 2016-03-13T15:18:01.583 回答
0

尝试改用 Inspector.Activate 事件。

于 2016-03-13T20:34:29.053 回答