Можно ли программно переименовать категорию Outlook?
-
18-09-2019 - |
Вопрос
Мы разрабатываем надстройку 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 "навсегда" с помощью кода?Майкрософт.Офис.Взаимодействие.Outlook.Категория не имеет методов Save (), Update () или Persist().
P.S.Мы разрабатываем надстройку Outlook 2007 с использованием Visual Studio 2008, .net 3.5, C # 3.Проблема воспроизводится в Outlook 2007 с пакетом обновления 1 и пакетом обновления 2.Другие версии Outlook не тестировались.
Решение
Я решил проблему (сама проблема, похоже, связана с ошибкой Outlook 2007) с помощью взлома.Следующие ссылки помогли мне создать хак (упс, недостаточно репутации, чтобы опубликовать более 1 ссылки):
- http ://blogs.officezealot.com/legault/archive/2009/08/13/21577.aspx
- http://www.officekb.com/Uwe/Forum.aspx/outlook-prog-addins/3142/Apply-Categories-to-other-users-Outlook-2007
- 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, возникающая в Outlook 2007 SP2.
"Рассмотрим следующий сценарий.У вас есть пользовательское приложение, которое можно запустить для создания новых категорий в Outlook 2007.Вы запускаете приложение для создания новой категории в Outlook 2007.Затем, если вы перезапустите Outlook 2007, созданная вами категория неожиданно будет удалена.Эта проблема возникает после установки февральского накопительного обновления или SP2."
Исправление доступно с 30 июня 2009 года:http://support.microsoft.com/default.aspx/kb/970944/en
С уважением, Тим