'Outlook add-in - Store and look up data as hidden StorageItem

I want to create a "local database" in Outlook, by storing some auxiliary data in a hidden form.

After investigating the object model, I found the StorageItem objects, that looked promising.

I managed to store some rows, and also look them up by their unique subject, however, I have trouble iterating through the StorageItems. It says in the object model, that there's no direct iterator available for the StorageItem object, but I could query a table from the same folder, that will have the StorageItems.

The table will end up containing 5 items, and none of them look anything like my stored items.

Here's my code that I currently use for inserting the StorageItems with some custom properties:

public static void InsertStorageItem(String UniqueID, String Name, String Address) 
{
    Outlook.NameSpace ns = null;
    Outlook.Folder tasksFolder = null;

    ns = outlookApp.Session;
    tasksFolder = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks) as Outlook.Folder;

    Outlook.StorageItem OIEDBTask = tasksFolder.GetStorage(UniqueID, Microsoft.Office.Interop.Outlook.OlStorageIdentifierType.olIdentifyBySubject);

    if (OIEDBTask.Size == 0)
    {
        OIEDBTask.UserProperties.Add("uniqueid", Microsoft.Office.Interop.Outlook.OlUserPropertyType.olText);
        OIEDBTask.UserProperties.Add("name", Microsoft.Office.Interop.Outlook.OlUserPropertyType.olText);
        OIEDBTask.UserProperties.Add("address", Microsoft.Office.Interop.Outlook.OlUserPropertyType.olText);
    }

    //assign values to custom properties
    OIEDBTask.UserProperties["uniqueid"].Value = UniqueID;
    OIEDBTask.UserProperties["name"].Value = Name;
    OIEDBTask.UserProperties["address"].Value = Address;

    OIEDBTask.Save();
}

Here's how I would like to query data:

public static dynamic QueryStorageItem() 
{
    List<dynamic> QueryResults = new List<dynamic>();
    Outlook.NameSpace ns = null;
    Outlook.Folder tasksFolder = null;
    Outlook.Table ResultTable = null;

    ns = outlookApp.Session;
    tasksFolder = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks) as Outlook.Folder;

    String Filter = "[LastModificationTime] > '5/1/2005'";  //tried removing the filter, but it didn't help. the comparison date is very old, so it should always give back some data
    ResultTable = tasksFolder.GetTable(Filter, Outlook.OlTableContents.olHiddenItems);

    while(!ResultTable.EndOfTable)  //tried a do-while structure also, didn't work.
    {
        Outlook.Row resultRow = ResultTable.GetNextRow();
        QueryResults.Add(resultRow.GetValues()); //the GetValues() function will give me an array with 5 objects in it, that are very different than my StorageItems
    }

    return QueryResults;
}

The main idea would be, to use the set up properties of the StorageItems, to use the Filtering, that is given by Outlook: for example, try to find all StorageItems, where the address is a certain value. Naturally, I would write a similar Filter string:

String Filter = "[address] = 'certain value'";

This doesn't work, and after reading up a little bit on it, I came to the conclusion, that it might not work, because they are custom UserProperties, and filtering should only work on built-in properties for the Outlook items, such as LastModificationTime and others.

However, even without filtering, the data set that I get back from the GetTable function is of no use. (So I can't iterate through the rows, and they don't represent any data or even structure, that I've inserted)

Any chance somebody could guide towards a better solution?

My main scope is, to store some auxiliary data, that is not visible to the user. If this is not the solution, then I would have to create tasks instead of StorageItems.



Solution 1:[1]

Storage (aka associated) items are just regular messages from the MAPI point of view (you can see them in OutlookSpy (I am its author) if you click IMAPIFolder button and go to the "Associated Contents" tab), it is just OOM decides to expose them very differently. Storage items in OOM are not really designed to be searched - the idea is that you create/open your private item by the subject or the message class and do not care or touch other storage items that you know nothing about.

One trick I can think of is to construct message class using the address itself (e.g. "[email protected]") and specify that message class when opening the storage item.

If you really want to search the associated table of contents, Extended MAPI (C++ or Delphi) or Redemption (I am also its author) are probably your only choices. Redemption exposes associated items in the same way it exposes the regular items, i.e. RDOFolder.HiddentItems vs RDOFolder.Items. You can then search using RDOItems.Find/FindNext/Restrict/MAPITable.ExecSQL.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1