是否可以通过编程方式重命名Outlook类别?
我们正在开发Outlook 2007附加模块。为了测试outlook类别重命名,我添加了以下代码块是否可以通过编程方式重命名Outlook类别?,outlook,add-in,outlook-2007,outlook-addin,office-interop,Outlook,Add In,Outlook 2007,Outlook Addin,Office Interop,我们正在开发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!!!"
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\u启动(对象发送方,事件参数e)
方法的末尾。
类别已重命名,但如果Outlook已关闭,则上面的行将被注释,Outlook将重新启动-类别名称不是我所期望的“TEST!!!”。它与重命名前一样是“Group1”。是否可以通过代码重命名outlook类别“永久”?Microsoft.Office.Interop.Outlook.Category没有Save()或Update()或Persist()方法
另外,我们正在使用Visual Studio 2008、.net 3.5、C#3开发Outlook 2007插件。
Outlook 2007 SP1和SP2重现了此问题。其他outlook版本没有经过测试。我已经用黑客软件解决了这个问题(问题本身似乎是outlook 2007的bug)。
以下链接帮助我创建了黑客(哎呀,没有足够的声誉发布超过1个链接):
- http://blogs.officezealot.com/legault/archive/2009/08/13/21577.aspx
- http://help.wugnet.com/office/set-master-category-list-Outlook-2007-ftopict1095935.html
- http://forums.slipstick.com/showthread.php?t=18189
- http://msdn.microsoft.com/en-us/library/ee203806%28EXCHG.80%29.aspx
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);
我已经用黑客解决了这个问题(问题本身似乎是Outlook 2007的bug)。
以下链接帮助我创建了黑客(哎呀,没有足够的声誉发布超过1个链接):
- http://blogs.officezealot.com/legault/archive/2009/08/13/21577.aspx
- http://help.wugnet.com/office/set-master-category-list-Outlook-2007-ftopict1095935.html
- http://forums.slipstick.com/showthread.php?t=18189
- http://msdn.microsoft.com/en-us/library/ee203806%28EXCHG.80%29.aspx
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);
这是Outlook 2007 SP2引入的Outlook错误 “考虑以下情况。您有一个自定义应用程序,可以运行该应用程序在Outlook 2007中创建新类别。 您运行应用程序以在Outlook 2007中创建一个新类别。然后,如果重新启动Outlook 2007,您创建的类别将意外删除。此问题发生在您安装2月份累积更新或SP2之后。” 自2009年6月30日起有可用的修补程序: 问候,,
Tim这是Outlook 2007 SP2引入的Outlook错误 “考虑以下情况。您有一个自定义应用程序,可以运行该应用程序在Outlook 2007中创建新类别。 您运行应用程序以在Outlook 2007中创建一个新类别。然后,如果重新启动Outlook 2007,您创建的类别将意外删除。此问题发生在您安装2月份累积更新或SP2之后。” 自2009年6月30日起有可用的修补程序: 问候,,
Tim我想知道这是否相关:Remou,谢谢你的评论,但不幸的是,提供的链接中描述的问题与以编程方式添加类别有关,并且仅与Outlook 2007 SP2相关。给定的解决方案无法解决我们面临的“重命名问题”。我想知道这是否相关:Remou,谢谢您的评论,但不幸的是,提供的链接中描述的问题与以编程方式添加类别有关,并且仅与Outlook 2007 SP2相关。给定的解决方案无法解决我们面临的“重命名问题”几乎相同的代码,但在VBA+赎回库中(200美元用于商业用途)。使用赎回获取类别列表不会抛出OfMemoryException。-几乎相同的代码,但在VBA+赎回库中(200美元用于商业用途)。使用redemption获取类别列表不会抛出OfMemoryException。Tim,不幸的是,这是相关的,但不是同一个bug。类别重命名的Bug不仅仅是SP2,正如我在前面的原始问题中提到的。Remou在一个月前写了和你一样的东西(见对我原始问题的评论)。与类别创建不同的是,它只是SP2,它有修补程序。而且热修复程序不能通过重命名解决bug。Tim,不幸的是,这是相关的,但不是相同的bug。类别重命名的Bug不仅仅是SP2,正如我在前面的原始问题中提到的。Remou在一个月前写了和你一样的东西(见对我原始问题的评论)。与类别创建不同的是,它只是SP2,它有修补程序。热修复程序并不能解决重命名的错误。