1

我们正在开发 Outlook 2007 插件。为了测试 Outlook 类别重命名,我添加了以下代码块

 var session = Application.Session;
 var categories = session.Categories;
 var category1 = session.Categories[1];

 //catefory1.Name is "Group1" before executing line below
 category1.Name = "TEST!!!";

 Marshal.ReleaseComObject(category1);
 Marshal.ReleaseComObject(categories);
 Marshal.ReleaseComObject(session);

到加载项private void ThisAddIn_Startup(object sender, EventArgs e)方法的末尾。类别已重命名,但如果 Outlook 已关闭,则注释上述行,并重新启动 Outlook - 类别名称不是“TEST!!!” 正如我所料。它是重命名前的“Group1”。是否可以通过代码将 Outlook 类别“永远”重命名?Microsoft.Office.Interop.Outlook.Category 没有 Save() 或 Update() 或 Persist() 方法。

PS 我们正在使用 Visual Studio 2008、.net 3.5、C# 3 开发 Outlook 2007 插件。该问题在 Outlook 2007 SP1 和 SP2 中重现。其他 Outlook 版本未经过测试。

4

2 回答 2

1

我已经使用 hack 解决了这个问题(问题本身似乎是 Outlook 2007 错误)。以下链接帮助我创建了黑客(哎呀,没有足够的声誉发布超过 1 个链接):

hack 本身如下所示:

using System;
using System.Text;
using System.Xml;
using System.IO;
using Microsoft.Office.Interop.Outlook;

namespace OutlookHack
{
    public static class OutlookCategoryHelper
    {
        private const string CategoryListStorageItemIdentifier = "IPM.Configuration.CategoryList";
        private const string CategoryListPropertySchemaName = @"http://schemas.microsoft.com/mapi/proptag/0x7C080102";
        private const string CategoriesXmlElementNamespace = "CategoryList.xsd";
        private const string XmlNamespaceAttribute = "xmlns";
        private const string CategoryElement = "category";
        private const string NameAttribute = "name";

        public static void RenameCategory(string oldName, string newName, Application outlookApplication)
        {
            MAPIFolder calendarFolder = outlookApplication.Session.GetDefaultFolder(
                OlDefaultFolders.olFolderCalendar);
            StorageItem categoryListStorageItem = calendarFolder.GetStorage(
                CategoryListStorageItemIdentifier, OlStorageIdentifierType.olIdentifyByMessageClass);

            if (categoryListStorageItem != null)
            {
                PropertyAccessor categoryListPropertyAccessor = categoryListStorageItem.PropertyAccessor;
                string schemaName = CategoryListPropertySchemaName;
                try
                {
                    // next statement raises Out of Memory error if property is too big
                    var xmlBytes = (byte[])categoryListPropertyAccessor.GetProperty(schemaName);

                    // the byte array has to be translated into a string and then the XML has to be parsed
                    var xmlReader = XmlReader.Create(new StringReader(Encoding.UTF8.GetString(xmlBytes)));

                    // xmlWriter will write new category list xml with renamed category
                    XmlWriterSettings settings = new XmlWriterSettings { Indent = true, IndentChars = ("\t") };
                    var stringWriter = new StringWriter();
                    var xmlWriter = XmlWriter.Create(stringWriter, settings);

                    xmlReader.Read(); // read xml declaration
                    xmlWriter.WriteNode(xmlReader, true);
                    xmlReader.Read(); // read categories
                    xmlWriter.WriteStartElement(xmlReader.Name, CategoriesXmlElementNamespace);
                    while (xmlReader.MoveToNextAttribute())
                    {
                        if (xmlReader.Name != XmlNamespaceAttribute) // skip namespace attr
                        {
                            xmlWriter.WriteAttributeString(xmlReader.Name, xmlReader.Value);
                        }
                    }
                    while (xmlReader.Read())
                    {
                        switch (xmlReader.NodeType)
                        {
                            case XmlNodeType.Element: // read category
                                xmlWriter.WriteStartElement(CategoryElement);
                                while (xmlReader.MoveToNextAttribute())
                                {
                                    if ((xmlReader.Name == NameAttribute) && (xmlReader.Value == oldName))
                                    {
                                        xmlWriter.WriteAttributeString(NameAttribute, newName);
                                    }
                                    else
                                    {
                                        xmlWriter.WriteAttributeString(xmlReader.Name, xmlReader.Value);
                                    }
                                }
                                xmlWriter.WriteEndElement();
                                break;
                            case XmlNodeType.EndElement: // categories ended
                                xmlWriter.WriteEndElement();
                                break;
                        }
                    }
                    xmlReader.Close();
                    xmlWriter.Close();

                    xmlBytes = Encoding.UTF8.GetBytes(stringWriter.ToString());
                    categoryListPropertyAccessor.SetProperty(schemaName, xmlBytes);
                    categoryListStorageItem.Save();
                }
                catch (OutOfMemoryException)
                {
                    // if error is "out of memory error" then the XML blob was too big
                }
            }
        }
    }
}

必须在类别重命名之前调用此辅助方法,例如:

 var session = Application.Session;
 var categories = session.Categories;
 var category1 = session.Categories[1];

 //catefory1.Name is "Group1" before executing line below
 OutlookCategoryHelper.RenameCategory(category1.Name, "TEST!!!", Application);
 category1.Name = "TEST!!!";

 Marshal.ReleaseComObject(category1);
 Marshal.ReleaseComObject(categories);
 Marshal.ReleaseComObject(session);
于 2010-01-06T11:51:48.423 回答
0

这是 Outlook 2007 SP2 中引入的一个 Outlook 错误。

“考虑以下场景。您有一个自定义应用程序,可以运行该应用程序以在 Outlook 2007 中创建新类别。您运行该应用程序以在 Outlook 2007 中创建新类别。然后,如果您重新启动 Outlook 2007,您创建的类别是意外删除。安装二月累积更新或 SP2 后会出现此问题。

自 2009 年 6 月 30 日起有一个可用的修补程序:http: //support.microsoft.com/default.aspx/kb/970944/en

问候,蒂姆

于 2010-03-02T08:55:40.273 回答