Apply Categories to other users Outlook 2007

  • Thread starter Thread starter Alex Yakhnin
  • Start date Start date
A

Alex Yakhnin

Hi all,

I have an VSTO Add-in Outlook 2007 application that is accessing other
user's shared calendars and created appointments for them. We also have a
set of custom colored Categories that must be applied to these appointments.
So I create the Categories by updating the Application.Session.Categories
and the appoinments show the correct colors in my calendar, but they don'ts
show up in the other user's shared calendars.

So here's the question: How can I create these Categories programmatically
for other users? I know that Microsoft has removed the Master List that was
stored in the registry for Outlook 2007.

I've been searching for this solution high and low, tried many different
approaches like using CDO, etc.. nothing works.

Thx... Alex
 
Categories are now stored as a hidden item in the default Calendar folder.
The hidden item (StorageItem for Outlook 2007) has a MessageClass of
"IPM.Configuration.CategoryList". The category information is stored as a
binary property (PT_BINARY) at property tag 0x7C080102. In DASL syntax that
would be "http://schemas.microsoft.com/mapi/proptag/0x7C080102".

The property can be accessed using the new PropertyAccessor, with a major
limitation. PropertyAccessor won't return binary streams that are larger
than XX KB, it just returns an out of memory error. We're still waiting for
MS to tell us what XX is, all we know so far is that it's store provider
dependent. You would be safe definitely if the binary XML blob is 4K or
smaller, most likely with 8K or smaller but you'd have to test on each store
type (PST, mailbox, custom store provider) to verify the limits.

What makes this limitation a real problem is that you can write larger
values than you can get back. So you could write a 12K blob with no errors
but get errors trying to read it. Plus it's so far undocumented and the
limits are undocumented. Outlook 2007 does not fall back to reading the
property as a Stream if the out of memory error occurs, as does CDO for one
example (due to "performance" reasons).

You could use CDO 1.21 to read the property correctly in all cases, but
that's being deprecated and isn't included in the Office distribution and
must be downloaded from the MS Web site now, so it may not be available. 3rd
party libraries such as Redemption (www.dimastr.com/redemption) don't have
this problem.

CDO 1.21 and Extended MAPI are also not supported in .NET code, BTW. They
may work in some cases but there are no guarantees and no support. They also
may work on your machine and fail in the field at the most important user of
that software and then you're really out of luck.
 
Hi Ken,

Thank you very much for this information!

So in my scenario, I would need to pull the calendar folder of the user and
update the CategoryList with my copy of this data?
Do you have any samples how to do it with PropertyAccessor? I get the error
""The property \"http://schemas.microsoft.com/mapi/proptag/0x7C080102\" is
unknown or cannot be found.". Here is my code:

string schema = @"http://schemas.microsoft.com/mapi/proptag/0x7C080102";
Outlook.MAPIFolder calendar=
app.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
Outlook.PropertyAccessor oPA = calendar.PropertyAccessor;
object Transport = oPA.GetProperty(schema);

Thx... Alex
--
Alex Yakhnin, Device Application Developer MVP
http://blog.opennetcf.org/ayakhnin


Ken Slovak - said:
Categories are now stored as a hidden item in the default Calendar folder.
The hidden item (StorageItem for Outlook 2007) has a MessageClass of
"IPM.Configuration.CategoryList". The category information is stored as a
binary property (PT_BINARY) at property tag 0x7C080102. In DASL syntax
that would be "http://schemas.microsoft.com/mapi/proptag/0x7C080102".

The property can be accessed using the new PropertyAccessor, with a major
limitation. PropertyAccessor won't return binary streams that are larger
than XX KB, it just returns an out of memory error. We're still waiting
for MS to tell us what XX is, all we know so far is that it's store
provider dependent. You would be safe definitely if the binary XML blob is
4K or smaller, most likely with 8K or smaller but you'd have to test on
each store type (PST, mailbox, custom store provider) to verify the
limits.

What makes this limitation a real problem is that you can write larger
values than you can get back. So you could write a 12K blob with no errors
but get errors trying to read it. Plus it's so far undocumented and the
limits are undocumented. Outlook 2007 does not fall back to reading the
property as a Stream if the out of memory error occurs, as does CDO for
one example (due to "performance" reasons).

You could use CDO 1.21 to read the property correctly in all cases, but
that's being deprecated and isn't included in the Office distribution and
must be downloaded from the MS Web site now, so it may not be available.
3rd party libraries such as Redemption (www.dimastr.com/redemption) don't
have this problem.

CDO 1.21 and Extended MAPI are also not supported in .NET code, BTW. They
may work in some cases but there are no guarantees and no support. They
also may work on your machine and fail in the field at the most important
user of that software and then you're really out of luck.
 
Answered privately off list. To recap for anyone following this:

I might not have been clear enough that the property isn't on the Folder
object but on a hidden item in the folder (a StorageItem). So after you get
the Folder you need to get the StorageItem with the MessageClass of
""IPM.Configuration.CategoryList". The categories are in XML but the XML
isn't stored as a PT_STRING8, it's stored as PT_BINARY. So it would be
retrieved as a byte array. Also, I'd be using Outlook.Folder instead of
MAPIFolder. MAPIFolder doesn't expose the new properties, methods or events
while Folder does.

Once you have your Folder you'd need something like this:

Outlook.StorageItem oSI = (Outlook.StorageItem)
calendar.GetStorage("IPM.Configuration.CategoryList",
Outlook.OlStorageIdentifierType.olIdentifyByMessageClass);

if(oSI != null)
{
// xml for category settings lives in the hidden item as a MAPI
property
oPA = oSI.PropertyAccessor;
Xml.XmlDocument xmldoc = new Xml.XmlDocument;
try
{
string schema =
@"http://schemas.microsoft.com/mapi/proptag/0x7C080102";

// next statement raises Out of Memory error if property is
too big
byte[] Transport = oPA.GetProperty(schema);

// the byte array has to be translated into a string and
then the XML has to be parsed
string xml = Encoding.UTF8.GetString(Transport);
xmldoc.LoadXml(xml); // this is the XML string extracted
from the binary blob
}
catch(Exception ex)
{
// if error is "out of memory error" then the XML blob was
too big
}
}

BTW, this would work with the user's default calendar folder, but would not
work if you get another user's calendar folder using
NameSpace.GetSharedDefaultFolder.
 
Back
Top