none
Outlook VSTO - "Could Not Read Calendar" error RRS feed

  • Question

  • One of our clients is trying to install our Outlook 2010 VSTO add-in which accesses the calendar folders and task folders.  The first time he opens Outlook after the install, he gets the "Could Not Read the Calendar" error.  He's the only one of our users that is experiencing this problem.  If he then uninstalls our add-in, the error no longer appears.  I have not been able to reproduce this problem on my test computer even with installing the other (Kapersky) add-ins that he is running.

    Would someone please give me an idea of what causes this error and what I can do now to try to fix this problem?


    Cindy
    Monday, August 22, 2011 7:24 PM

Answers

  • The RPC limit is enforced by the Exchange server. On the  client side you can only make sure that you do not open too many objects.

    Once again, multiple dot notation is evil, do not call cf.Items.Find.

    Cache the cf.Items collection in a local variable before entering the loop.


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

    Monday, November 28, 2011 9:36 PM

All replies

  • Does this error come from Outlook or from your add-in?
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Monday, August 22, 2011 7:30 PM
  • Yes, it is coming from Microsoft Outlook.  I'm still waiting for him to turn on the VSTO Error alerts/logging to see if a VSTO error will popup.  
    Cindy
    Monday, August 22, 2011 8:21 PM
  • What does your code do on start up?
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Tuesday, August 23, 2011 4:50 AM
  • Basically it sets all the item/folder module level vars and events.  

     

     

          private void ThisAddIn_Startup(object sender, System.EventArgs e)
          {
    Application.OptionsPagesAdd += new Outlook.ApplicationEvents_11_OptionsPagesAddEventHandler(Application_OptionsPagesAdd); Application.Inspectors.NewInspector += new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector); currentExplorer = Application.ActiveExplorer(); currentExplorer.SelectionChange += new Outlook.ExplorerEvents_10_SelectionChangeEventHandler(currentExplorer_SelectionChange); currentExplorer.BeforeFolderSwitch += new Outlook.ExplorerEvents_10_BeforeFolderSwitchEventHandler(currentExplorer_BeforeFolderSwitch); _reminders = Application.Reminders; _reminders.ReminderFire += new Outlook.ReminderCollectionEvents_ReminderFireEventHandler(_reminders_ReminderFire); //folder collections _ns = Application.GetNamespace("MAPI"); _taskFolder = _ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderTasks); _delFolder = _ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderDeletedItems); _calFolder = _ns.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar); //item collections _taskItems = _taskFolder.Items; _calendarItems = _calFolder.Items; _deletedItems = _delFolder.Items; _deletedItems.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(deletedItems_ItemAdd); //recurse events to existing folders SetFolderEvents2(_taskFolder, _taskItems, true); SetFolderEvents2(_calFolder, _calendarItems, true); } //set ItemAdd/Change events private void SetFolderEvents2(Outlook.MAPIFolder Folder, Outlook.Items items, bool recurse) { //set event based on type of item if (Folder.DefaultItemType == Outlook.OlItemType.olTaskItem) { items.ItemChange += new Outlook.ItemsEvents_ItemChangeEventHandler(taskItems_ItemChange); items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd); } else if (Folder.DefaultItemType == Outlook.OlItemType.olAppointmentItem) { items.ItemChange += new Outlook.ItemsEvents_ItemChangeEventHandler(calendarItems_ItemChange); items.ItemAdd += new Outlook.ItemsEvents_ItemAddEventHandler(items_ItemAdd); } else { return; } _folders.Add(Folder); _folderitems.Add(items); Outlook.Folders fs = Folder.Folders; fs.FolderAdd += new Outlook.FoldersEvents_FolderAddEventHandler(Folders_FolderAdd); _subfolders.Add(fs); if (recurse) { //process children foreach (Outlook.MAPIFolder f in Folder.Folders) { Outlook.Items fi = f.Items; SetFolderEvents2(f, fi, false); } } }


     


    Cindy
    Tuesday, August 23, 2011 7:20 PM
  • Have you been able to determine anything about this problem?  I need to get back to the client and I don't know what to try next.  Any suggestions would be greatly appreciated!
    Cindy
    Tuesday, September 6, 2011 2:02 PM
  • Can you use MAPILogonComplete event instead of Startup?
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Tuesday, September 6, 2011 7:40 PM
  • Dmitry,

     

    I could never get that client to try the new version, however, now I have another client receiving the "Could Not Read Calendar" error using a 64-bit version of the add-in that I already changed to use Application_MAPILogonComplete.  Any further ideas? 

     


    Cindy
    Monday, October 17, 2011 5:12 PM
  • What is the client's setup? Is it PST? Exchange? IMAP?
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    Tuesday, October 18, 2011 8:00 PM
  • They are using Exchange.
    Cindy
    Tuesday, October 18, 2011 8:23 PM
  • Hmmm... I can only think of trying to catch the error and fire up a timer to set up the event sink at the later time...
    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    Tuesday, October 18, 2011 9:42 PM
  • Dmitry,

     

    I had no luck catching the errors in my Add-in because they come from Outlook and not through VSTO.  Is there an event in VSTO that catches Outlook errors?  Like Application_OnError or something similar? I couldn't find one. 

    I did find the segment of code that is causing the issue through a lengthy process of elimination.  Mind you, it works on my test computers, just not on the computers at the client's location.  Also, it only causes an issue if they set our synchronization in our add-in to run every X minutes and they just happen to try to access a calendar item/folder when the sync is running in the background.  So it doesn't happen all the time, but it definitely seems like a locking of resources problem.  What's odd is multiple things happen on sync, but only this section of code causes issues.

    Basically, this segment of code is determining if a Calendar item that our add-in created in Outlook has been deleted in our application.  So it loops through the applicable Outlook calendar items (they have our GUID in a User Property) and if that GUID is not found in the items from our web service request, it deletes the item from Outlook.  

    This code has try{}catch{} normally with file logging.  I took those out to save space here.  It hasn't produced errors itself, only causes Outlook to error.

     

    Outlook.AppointmentItem appt = null;
    int i = 0;
    string g = string.Empty;
    bool bDelete = false;
    Outlook.MAPIFolder cf = null;
    
    //returns default folder for Calendar Items
    cf = GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
    
    //GetAllCOL4Events - loops through all Calendar events and returns the GUIDs of ones linked to our application
    List<String> COLappts = OLK.GetAllCOL4Events(cf, true);                
    
    for (i = 0; i < COLappts.Count; i++)
    {
           	bDelete = false;
            g = COLappts[i];
                            
            //get appointment object with current GUID in our User Property
            appt = (Outlook.AppointmentItem)cf.Items.Find("[" + Global.UP_GUID + "]='" + g + "'");
    
            if (appt != null)
            {
               	//if GUID is not in our results, it was deleted
                    if (!CheckForGUID(er, g))  //loops through our array of objects from our system
                    {
     	               appt.Delete();
                           bDelete = true;
                    }
            }
                            
    	//Close object with Save
            if (!bDelete && appt!=null)
            {
            	((Outlook._AppointmentItem)appt).Close(Outlook.OlInspectorClose.olSave);
            }
            
            if (appt != null) { Marshal.ReleaseComObject(appt); }
            Marshal.ReleaseComObject(cf);
            GC.Collect(); 
    }      
    
    COLappts.Clear();
    

     


    What am I doing wrong here?  We are considering removing the option for auto-syncing every X minutes to resolve the issue.  I would like to keep it in there though if possible.  It seems like other add-ins do that successfully without conflicting with Outlook.

    Thanks,

     


    Cindy
    • Edited by HorseFly Monday, November 28, 2011 9:12 PM
    Monday, November 28, 2011 9:11 PM
  • Is that a cached or an online profile?

    Is it posible that you open too many appointments and run out of RPC channels?

    Also, you are using multiple dot notation (cf.Items.Find), which is never a good idea, especially in a loop.


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.2 is now available!
    Monday, November 28, 2011 9:18 PM
  • I would guess a cached profile if that is the default.

    We had been receiving the RPC limit error awhile back, but it went away once I combed through and added the Close() and Marshal.ReleaseComObject calls.  It was popping up long before we got to this segment of code, but I haven't seen it come up at all in several rounds of testing now.  I am unsure how those connections work.  In my loops, I close and release the item after accessing it, so wouldn't it only have 1 item open at a time?  Is there any way to tell how many RPC connections it has open? 

    I will fix the multiple dot notation and see if that helps. 


    Cindy
    Monday, November 28, 2011 9:32 PM
  • The RPC limit is enforced by the Exchange server. On the  client side you can only make sure that you do not open too many objects.

    Once again, multiple dot notation is evil, do not call cf.Items.Find.

    Cache the cf.Items collection in a local variable before entering the loop.


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

    Monday, November 28, 2011 9:36 PM
  • Dmitry,


    Thanks for your help!  The error went away once I got rid of the multiple dot notation.  Luckily, there were only a few instances that I had missed in the project.

     


    Cindy
    Monday, December 5, 2011 5:24 PM