I need to get EntryIDs for all contacts in Outlook folder. If I have 6000 contacts in a folder, it takes about 100 seconds to execute (it doesn't matter much if if's background thread or main thread, I tried both). The code is like this:
List<Outlook.ContactItem> contactItemsList = null;
Outlook.Items folderItems = null;
Outlook.MAPIFolder folderSuggestedContacts = null;
Outlook.NameSpace ns = null;
Outlook.MAPIFolder folderContacts = null;
object itemObj = null;
try
{
contactItemsList = new List<Outlook.ContactItem>();
ns = Application.GetNamespace("MAPI");
// getting items from the Contacts folder in Outlook
folderContacts = ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
folderItems = folderContacts.Items;
for (int i = 1; folderItems.Count >= i; i++)
{
itemObj = folderItems[i];
if (itemObj is Outlook.ContactItem)
contactItemsList.Add(itemObj as Outlook.ContactItem);
else
Marshal.ReleaseComObject(itemObj);
}
Marshal.ReleaseComObject(folderItems);
folderItems = null;
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message);
}
finally
{
if (folderItems != null)
Marshal.ReleaseComObject(folderItems);
if (folderContacts != null)
Marshal.ReleaseComObject(folderContacts);
if (folderSuggestedContacts != null)
Marshal.ReleaseComObject(folderSuggestedContacts);
if (ns != null)
Marshal.ReleaseComObject(ns);
}
var ids = contactItemsList.Select(c => c.EntryID).ToArray();
The part to collect items takes about 5-8 seconds while the last line takes about 80-90 seconds.
Is there a faster way? I thought of Items.SetColumns initially but it turns out it doesn't work for EntryID (which seems strange decision of Outlook developers as EntryID is just a string and SetColumns is intended for quick retrieval of string properties).
Moreover, Outlook almost freezes for all this time (~100 seconds) even with BackgroundWorker. You can accidentally click something but it's like FPS rate is 1-2 FPS or so. It seems background execution doesn't help much. I suspect it's because background execution is great when the task being executed is not CPU-intensive but getting EntryIDs is heavy operation and thus severely interferes with UI.
I also have some legacy C++/COM code which does the same and it's slow as well. Looks like .NET interop is not the root cause of the issue. Maybe there is another API call which I should use for that?
I'm currently testing with Outlook 2010 64-bit.