none
Outlook Interop performance RRS feed

  • Question

  • Hi,

    Is there a way to speed upp this code or do it better in a performance perspective? I want to get outlook items in a specific folder. In the folder there are aprox 6000 items and there is mostly one or sometimes 2-3 items that fits my restriction. I have a log function and this line of code takes about a second, oMailItem = items[i];. It maybe sounds little but in this case he performance is important.

    protected static List<SupportMailItem> GetOutlookItemsWithTicketNumberInSubject(string sTicketNo)
            {
    
                SupportMailItem oSupportMailitem = null;
                List<SupportMailItem> lsSupportMailItem = new List<SupportMailItem>();
                Outlook.Items items = null;
                Outlook.MailItem oMailItem = null;
                Outlook.Application oOutlookApplication = null; 
                Outlook.NameSpace oOutlookNameSpace = null; 
                try
                {
                    oOutlookApplication = new Outlook.Application();
                    oOutlookNameSpace = oOutlookApplication.GetNamespace("MAPI");
                    string sFilter = "@SQL=" + "\"" + "urn:schemas:httpmail:subject" + "\"" + " like '%"+sTicketNo+"%'";
    
                    
                    foreach (Outlook.MAPIFolder folders in oOutlookNameSpace.Folders)
                    {
                        if (folders.Name.Contains("Gemensamma mappar")) //I need to have this beacuse this has different names in different outlook versions.
                        {
    
                            items = folders.Folders["Alla gemensamma mappar"].Folders["Support"].Folders["Ankomna"].Items.Restrict(sFilter);
    
                        }
                    }
                for (int i = 1; i <= items.Count; i++)
                    {
    
                        oMailItem = items[i];
    
    
                        oSupportMailitem = new SupportMailItem(oMailItem.EntryID);
    
                        oSupportMailitem.Subject = oMailItem.Subject;
                        oSupportMailitem.Sender = oMailItem.Sender.Name;
                                           lsSupportMailItem.Add(oSupportMailitem);                   
    
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Fel", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    Marshal.ReleaseComObject(oMailItem);
                    Marshal.ReleaseComObject(items);
                    Marshal.ReleaseComObject(oOutlookApplication);
                    Marshal.ReleaseComObject(oOutlookNameSpace);
                    oMailItem = null;
                    items = null;
                    oOutlookApplication = null;
                    oOutlookNameSpace = null;
                }
    
                return lsSupportMailItem;            
                
            }

    Thursday, December 29, 2016 12:24 PM

Answers

  • Aha i see. Likte this instead? Then i realese the objects in the end.

    oFolderParent = oOutlookNameSpace.Folders[i];
    oFolderChild1 = oFolderParent.Folders["Alla gemensamma mappar"];
    oFolderChild2 = oFolderChild1.Folders["Support"];
    oFolderChild3 = oFolderChild2.Folders["Ankomna"];
    items = oFolderChild3.Items.Restrict(sFilter);

    • Marked as answer by Ollza Monday, January 2, 2017 12:43 PM
    Friday, December 30, 2016 9:04 AM

All replies

  • Use Items.Findd/FindNext or Items.Restrict to only process the items that fit your criteria.

    You can also use MAPIFolder.GetTable to retrieve properties from multiple items without opening them. 


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Thursday, December 29, 2016 2:09 PM
  • Hello Ollza,

    First of all, don't use the foreach cycles in the code. Use the for loop instead. Or you will not be able to release underlying COM objects in the code instantly. Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. See Systematically Releasing Objects for more information.

    folders.Folders["Alla gemensamma mappar"].Folders["Support"].Folders["Ankomna"].Items.Restrict(sFilter);

    Also don't use multiple dots in the single line of code. Underlying COM objects will be left alive in that case. 

    To retrieve items that correspond to your conditions you can use the Find/FindNext or Restrict method of the Items class. In that case you will be able to get items form the single folder only. 

    How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)

    How To: Use Restrict method to retrieve Outlook mail items from a folder

    If you want to get items from multiple folders you need to use the AdvancedSearch method of the Application class.   

    Advanced search in Outlook programmatically: C#, VB.NET

    The key benefits of using the AdvancedSearch method in Outlook are:

    •  - The search is performed in another thread. You don’t need to run another thread manually since the AdvancedSearch method runs it automatically in the background.
    •  - Possibility to search for any item types: mail, appointment, calendar, notes etc. in any location, i.e. beyond the scope of a certain folder. The Restrict and Find/FindNext methods can be applied to a particular Items collection (see the Items property of the Folder class in Outlook).
    •  - Full support for DASL queries (custom properties can be used for searching too). You can read more about this in the Filtering article in MSDN. To improve the search performance, Instant Search keywords can be used if Instant Search is enabled for the store (see the IsInstantSearchEnabled property of the Store class).
    •  - You can stop the search process at any moment using the Stop method of the Search class.

    profile for Eugene Astafiev at Stack Overflow, Q&A for professional and enthusiast programmers


    Thursday, December 29, 2016 7:50 PM
  • Many thanks!

    Don´t understand "Also don't use multiple dots in the single line of code. Underlying COM objects will be left alive in that case. " Where in my code do i have that and how can i change it?

    Friday, December 30, 2016 7:17 AM
  • For example, I have noticed the following line of code:

    folders.Folders["Alla gemensamma mappar"].Folders["Support"].Folders["Ankomna"].Items.Restrict(sFilter);
    The Folders property of the Folder class returns an instance of the corresponding class (the Folders class) which should be released after. Then you call the indexer property to get a particular folder. The returned instance of the Folder class is not released too. Then you repeat such calls multiple times in the single line of code. Don't use chain of property and method calls in the single line. A lot of underlying COM objects will be left alive in memory (not released). Read more about that in the Systematically Releasing Objects article.


    profile for Eugene Astafiev at Stack Overflow, Q&A for professional and enthusiast programmers

    Friday, December 30, 2016 7:58 AM
  • Aha i see. Likte this instead? Then i realese the objects in the end.

    oFolderParent = oOutlookNameSpace.Folders[i];
    oFolderChild1 = oFolderParent.Folders["Alla gemensamma mappar"];
    oFolderChild2 = oFolderChild1.Folders["Support"];
    oFolderChild3 = oFolderChild2.Folders["Ankomna"];
    items = oFolderChild3.Items.Restrict(sFilter);

    • Marked as answer by Ollza Monday, January 2, 2017 12:43 PM
    Friday, December 30, 2016 9:04 AM
  • You still don't release all underlying COM objects instantly. For example:

    oFolderChild2 = oFolderChild1.Folders["Support"];

    The Folders property of the Folder class returns an instance of the corresponding class which should be released after. 

    items = oFolderChild3.Items.Restrict(sFilter);

    The Items property of the Folder class returns an instance of the corresponding class from the OOM. It should be released after as well. 


    profile for Eugene Astafiev at Stack Overflow, Q&A for professional and enthusiast programmers

    Monday, January 2, 2017 6:13 PM