none
Appointments not showing up in Outlook as I iterate through the folders collection RRS feed

  • Question

  • Hi,

       I have several appointments on the calendar but some are not showing up as I iterate through the folders collection recursively.      The code to kick the procedure off is. Is there a way that a calendar cannot be attached to a folder or could I have created an appointment that was connected to a folder and thus the appointment shows up in this case. Basically, in the Outlook object model are appointments always attached to some folder or a calendar to a folder and/or can there be appointments not attached to folders?

                ns = application.GetNamespace("MAPI");

                Dictionary<string, int> dLoop = new Dictionary<string,int>();

                RecurseThroughFolders(ns.Folders.GetFirst(), ns.Folders, request, dLoop, false);

    Sunday, August 9, 2015 3:57 AM

Answers

  • The following code will never work - you call MAPIFoldert.Items every time and get back a band new COM object on every call:

    if (k == 0) { ap = folder.Items.GetFirst() as Outlook.AppointmentItem; } else { ap = folder.Items.GetNext() as Outlook.AppointmentItem; }

    Secondly, you have a double loop using "for" and "GetFirst/GetNext". Use one or the other. You can also use "foreach":

    Outlook.Items items = folder.Items;
    
    //"for" loop - note it is 1 based
    for (int k = 1; k <= items.Count; k++)
    {
      OulookAppointment apt = items[k];
      ...
    }
    
    //foreach loop
    foreach (Outlook.Appointment apt in items)
    {
      ...
    }
    
    //GetFirst/GetNext loop
    (Outlook.Appointment apt = items.GetFirst();
    while (apt != null)
    {
      ..
      apt = items.GetNext();
    }


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

    Sunday, August 9, 2015 4:25 PM

All replies

  • Please show your code. Looking at the snippet above, it looks like you call GetFirst on a collection that is not used afterwards. If you implementation of RecurseThroughFolders calls Folders.GetNext() as on the second parameter, you will *not* end up with folder #2, you will still get folder number one - each time you call ns.Folders, you end up with a brand new COM object that has no knowledge of any other instances.

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

    Sunday, August 9, 2015 5:59 AM
  • Hello Mike,

    Calendars are represented by folders in Outlook. And appointment items are stored in folders.

     RecurseThroughFolders(ns.Folders.GetFirst(), ns.Folders, request, dLoop, false); 

    Don't use multiple dots in the single line of code when you deal with the Outlook object model. The Folders property returns an instance of the Folders collection that represents all the folders contained in the specified Folder. Then the GetFirst method of the Folders class is used to get the first object in the Folders collection. Each time you call property or method a new/separate instance is returned which should also be released after.

    Use System.Runtime.InteropServices.Marshal.ReleaseComObject to release an Outlook object when you have finished using it. This is particularly important if your add-in attempts to enumerate more than 256 Outlook items in a collection that is stored on a Microsoft Exchange Server. If you do not release these objects in a timely manner, you can reach the limit imposed by Exchange on the maximum number of items opened at any one time. Then set a variable to Nothing in Visual Basic (null in C#) to release the reference to the object. Read more about that in the Systematically Releasing Objects article.

    Sunday, August 9, 2015 9:25 AM
  • Thanks Eugene.
    Sunday, August 9, 2015 11:42 AM
  •         private void RecurseThroughFolders(Outlook.MAPIFolder folder, Outlook.Folders folders, Request request, bool skip)
            {

                Outlook.AppointmentItem ap = null;

                int ndx = 0;

                if (folder == null)
                {
                    return;
                }

                if (!skip)
                {

                    for (int k = 0; k < folder.Items.Count; k++)
                    {
                        Appointment apcrm = new Appointment();

                        if (k == 0)
                        {
                            ap = folder.Items.GetFirst() as Outlook.AppointmentItem;
                        }
                        else
                        {
                            ap = folder.Items.GetNext() as Outlook.AppointmentItem;
                        }

                        if (ap == null)
                        {
                            continue;
                        }

                        if (ap.Start < DateTime.Parse(request.StartDate) || ap.End > DateTime.Parse(request.EndDate + " 23:59:59"))
                        {
                            continue;
                        }

                        if (ap.UserProperties != null)
                        {
                            Outlook.UserProperty property = ap.UserProperties.Find("activityid", true);

                            if (property != null)
                            {
                                apcrm.ActivityId = property.Value;
                            }
                        }

                        apcrm.FolderId = ap.Parent.EntryID;
                        apcrm.EntryId = ap.EntryID;
                        apcrm.Describe = ap.Body;
                        apcrm.EventStart = ap.Start.ToShortDateString();
                        apcrm.EventEnd = ap.End.ToShortDateString();
                        apcrm.Subject = ap.Subject;
                        apcrm.StartTime = ap.Start.TimeOfDay.ToString();
                        apcrm.EndTime = ap.End.TimeOfDay.ToString();
                        apcrm.CreateDate = ap.CreationTime.ToString();
                        apcrm.LastModified = ap.LastModificationTime.ToString();
                        apcrm.PercentComplete = "0";
                        apcrm.ActivityId = "-1";
                        apcrm.ActivityType = "-1";
                        apcrm.SubActivityId = "-1";
                        apcrm.EntityId = "-1";
                        apcrm.EntityType = "-1";

                        if (ap.UserProperties != null)
                        {
                            Outlook.UserProperty property = ap.UserProperties.Find("entityid", true);

                            if (property != null)
                            {
                                apcrm.EntityId = property.Value;
                            }

                            property = ap.UserProperties.Find("entitytype", true);

                            if (property != null)
                            {
                                apcrm.EntityType = property.Value;
                            }
                        }

                        if (ap.Importance == Outlook.OlImportance.olImportanceHigh)
                        {
                            apcrm.Priority = "1";
                        }

                        if (ap.Importance == Outlook.OlImportance.olImportanceNormal)
                        {
                            apcrm.Priority = "2";
                        }

                        if (ap.Importance == Outlook.OlImportance.olImportanceLow)
                        {
                            apcrm.Priority = "3";
                        }

                        Outlook.RecurrencePattern rp = ap.GetRecurrencePattern();

                        if (ap.IsRecurring)
                        {
                            if (rp.RecurrenceType == Outlook.OlRecurrenceType.olRecursDaily)
                            {
                                apcrm.Recurs = "1";
                            }

                            if (rp.RecurrenceType == Outlook.OlRecurrenceType.olRecursWeekly)
                            {
                                apcrm.Recurs = "2";
                            }

                            if (rp.RecurrenceType == Outlook.OlRecurrenceType.olRecursMonthly)
                            {
                                apcrm.Recurs = "3";
                            }

                            if (rp.RecurrenceType == Outlook.OlRecurrenceType.olRecursYearly)
                            {
                                apcrm.Recurs = "4";
                            }

                            int toBase = 2;

                            rp.DayOfWeekMask = Outlook.OlDaysOfWeek.olThursday;

                            string binary = Convert.ToString(Convert.ToInt32(rp.DayOfWeekMask), toBase);

                            binary = binary.PadLeft(8, '0');

                            if (!string.IsNullOrEmpty(binary))
                            {
                                apcrm.Sunday = "0";
                                apcrm.Monday = "0";
                                apcrm.Tuesday = "0";
                                apcrm.Wednesday = "0";
                                apcrm.Thursday = "0";
                                apcrm.Friday = "0";
                                apcrm.Saturday = "0";

                                string sbit = binary.Substring(0, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Sunday = "1";
                                }

                                sbit = binary.Substring(1, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Monday = "1";
                                }

                                sbit = binary.Substring(2, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Tuesday = "1";
                                }

                                sbit = binary.Substring(3, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Wednesday = "1";
                                }

                                sbit = binary.Substring(4, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Thursday = "1";
                                }

                                sbit = binary.Substring(5, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Friday = "1";
                                }

                                sbit = binary.Substring(6, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Saturday = "1";
                                }
                            }

                            apcrm.RecursEvery = Convert.ToString(rp.Interval);

                            if (ap.ReminderMinutesBeforeStart > 0)
                            {
                                apcrm.RemindMe = "1";
                            }
                            else
                            {
                                apcrm.RemindMe = "0";
                            }

                            //not mapped
                            //task.SubActivityId = "";
                        }

                        request.AppointmentList.Add(apcrm);

                    }

                    folders = folder.Folders;

                }
                else
                {
                    Outlook.MAPIFolder mf = folders.GetFirst();

                    ndx = 0;
                    
                    while (true)
                    {
                        if (folder.EntryID == mf.EntryID)
                        {
                            ndx++;
                            break;
                        }

                        mf = folders.GetNext();

                        ndx++;
                    }
                }

                if (folders.Count > 0)
                {
                    for (int i = ndx; i < folders.Count; i++)
                    {
                        if (i == 0)
                        {
                            folder = folders.GetFirst();
                            folders = folder.Folders;

                            RecurseThroughFolders(folder, folders, request, false);
                        }
                        else
                        {
                            folder = folders.GetNext();
                            folders = folder.Folders;
                            
                            RecurseThroughFolders(folder, folders, request, false);

                        }
                    }
                }
                else
                {
                    folders = folders.Parent.Parent.Folders; //folder.Folders;
                    RecurseThroughFolders(folder, folders, request, true);
                }
            }
    Sunday, August 9, 2015 11:46 AM
  •         private void RecurseThroughFolders(Outlook.MAPIFolder folder, Outlook.Folders folders, Request request, bool skip)
            {

                Outlook.AppointmentItem ap = null;

                int ndx = 0;

                if (folder == null)
                {
                    return;
                }

                if (!skip)
                {

                    for (int k = 0; k < folder.Items.Count; k++)
                    {
                        Appointment apcrm = new Appointment();

                        if (k == 0)
                        {
                            ap = folder.Items.GetFirst() as Outlook.AppointmentItem;
                        }
                        else
                        {
                            ap = folder.Items.GetNext() as Outlook.AppointmentItem;
                        }

                        if (ap == null)
                        {
                            continue;
                        }

                        if (ap.Start < DateTime.Parse(request.StartDate) || ap.End > DateTime.Parse(request.EndDate + " 23:59:59"))
                        {
                            continue;
                        }

                        if (ap.UserProperties != null)
                        {
                            Outlook.UserProperty property = ap.UserProperties.Find("activityid", true);

                            if (property != null)
                            {
                                apcrm.ActivityId = property.Value;
                            }
                        }

                        apcrm.FolderId = ap.Parent.EntryID;
                        apcrm.EntryId = ap.EntryID;
                        apcrm.Describe = ap.Body;
                        apcrm.EventStart = ap.Start.ToShortDateString();
                        apcrm.EventEnd = ap.End.ToShortDateString();
                        apcrm.Subject = ap.Subject;
                        apcrm.StartTime = ap.Start.TimeOfDay.ToString();
                        apcrm.EndTime = ap.End.TimeOfDay.ToString();
                        apcrm.CreateDate = ap.CreationTime.ToString();
                        apcrm.LastModified = ap.LastModificationTime.ToString();
                        apcrm.PercentComplete = "0";
                        apcrm.ActivityId = "-1";
                        apcrm.ActivityType = "-1";
                        apcrm.SubActivityId = "-1";
                        apcrm.EntityId = "-1";
                        apcrm.EntityType = "-1";

                        if (ap.UserProperties != null)
                        {
                            Outlook.UserProperty property = ap.UserProperties.Find("entityid", true);

                            if (property != null)
                            {
                                apcrm.EntityId = property.Value;
                            }

                            property = ap.UserProperties.Find("entitytype", true);

                            if (property != null)
                            {
                                apcrm.EntityType = property.Value;
                            }
                        }

                        if (ap.Importance == Outlook.OlImportance.olImportanceHigh)
                        {
                            apcrm.Priority = "1";
                        }

                        if (ap.Importance == Outlook.OlImportance.olImportanceNormal)
                        {
                            apcrm.Priority = "2";
                        }

                        if (ap.Importance == Outlook.OlImportance.olImportanceLow)
                        {
                            apcrm.Priority = "3";
                        }

                        Outlook.RecurrencePattern rp = ap.GetRecurrencePattern();

                        if (ap.IsRecurring)
                        {
                            if (rp.RecurrenceType == Outlook.OlRecurrenceType.olRecursDaily)
                            {
                                apcrm.Recurs = "1";
                            }

                            if (rp.RecurrenceType == Outlook.OlRecurrenceType.olRecursWeekly)
                            {
                                apcrm.Recurs = "2";
                            }

                            if (rp.RecurrenceType == Outlook.OlRecurrenceType.olRecursMonthly)
                            {
                                apcrm.Recurs = "3";
                            }

                            if (rp.RecurrenceType == Outlook.OlRecurrenceType.olRecursYearly)
                            {
                                apcrm.Recurs = "4";
                            }

                            int toBase = 2;

                            rp.DayOfWeekMask = Outlook.OlDaysOfWeek.olThursday;

                            string binary = Convert.ToString(Convert.ToInt32(rp.DayOfWeekMask), toBase);

                            binary = binary.PadLeft(8, '0');

                            if (!string.IsNullOrEmpty(binary))
                            {
                                apcrm.Sunday = "0";
                                apcrm.Monday = "0";
                                apcrm.Tuesday = "0";
                                apcrm.Wednesday = "0";
                                apcrm.Thursday = "0";
                                apcrm.Friday = "0";
                                apcrm.Saturday = "0";

                                string sbit = binary.Substring(0, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Sunday = "1";
                                }

                                sbit = binary.Substring(1, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Monday = "1";
                                }

                                sbit = binary.Substring(2, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Tuesday = "1";
                                }

                                sbit = binary.Substring(3, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Wednesday = "1";
                                }

                                sbit = binary.Substring(4, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Thursday = "1";
                                }

                                sbit = binary.Substring(5, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Friday = "1";
                                }

                                sbit = binary.Substring(6, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Saturday = "1";
                                }
                            }

                            apcrm.RecursEvery = Convert.ToString(rp.Interval);

                            if (ap.ReminderMinutesBeforeStart > 0)
                            {
                                apcrm.RemindMe = "1";
                            }
                            else
                            {
                                apcrm.RemindMe = "0";
                            }

                            //not mapped
                            //task.SubActivityId = "";
                        }

                        request.AppointmentList.Add(apcrm);

                    }

                    folders = folder.Folders;

                }
                else
                {
                    Outlook.MAPIFolder mf = folders.GetFirst();

                    ndx = 0;
                    
                    while (true)
                    {
                        if (folder.EntryID == mf.EntryID)
                        {
                            ndx++;
                            break;
                        }

                        mf = folders.GetNext();

                        ndx++;
                    }
                }

                if (folders.Count > 0)
                {
                    for (int i = ndx; i < folders.Count; i++)
                    {
                        if (i == 0)
                        {
                            folder = folders.GetFirst();
                            folders = folder.Folders;

                            RecurseThroughFolders(folder, folders, request, false);
                        }
                        else
                        {
                            folder = folders.GetNext();
                            folders = folder.Folders;
                            
                            RecurseThroughFolders(folder, folders, request, false);

                        }
                    }
                }
                else
                {
                    folders = folders.Parent.Parent.Folders; //folder.Folders;
                    RecurseThroughFolders(folder, folders, request, true);
                }
            }
    Sunday, August 9, 2015 11:47 AM
  • The code is still pretty raw but you will notice is that it does not play well in the sense of retaining state on the recursive call. It appears and admittedly I am not a Outlook code expert that I had to reposition the folder pointer to the last folder entryid then run through the loop as it does not appear to retain state so I need an initial state of where it last left off. What also makes it difficult in the object model is the lack of syntactical ability to address the collection with an index as in collection[i] but I have to resort to GetNext, .... calls which makes it seemingly tough in recursive calls unless I am not understanding. I am pretty sure I passed the folders back into the recursive call and I tested if the state of the last GetNext was retained so I did not have to have the preamble initiator but it did not appear to have that state retained and it can be that a new object is being initiated which I am aware of thus defuncting that previous state
    Sunday, August 9, 2015 11:54 AM
  • Hello Mike,

    I still see multiple dots in the single line of code, for example:

    ap.UserProperties.Find

    and

     folders.Parent.Parent.Folders

    You need to review the code and break the chain of property and method calls, release all underlying COM objects instantly.

    Sunday, August 9, 2015 11:57 AM
  • Hi Dmitry,

       Code is posted with a comment below.

    Sunday, August 9, 2015 12:01 PM
  • Looking at your comment closer can this be the reason why I am having to use the initiator as mentioned in the comment to position the state of the collection to the last iterated entry id? I would like to pass the folders back but not have a new object so the state is maintained internally.
    Sunday, August 9, 2015 12:04 PM
  • Try to use the indexer property available in C# instead for accessing items in Outlook, for example:

    items[1];

    Sunday, August 9, 2015 3:23 PM
  • The following code will never work - you call MAPIFoldert.Items every time and get back a band new COM object on every call:

    if (k == 0) { ap = folder.Items.GetFirst() as Outlook.AppointmentItem; } else { ap = folder.Items.GetNext() as Outlook.AppointmentItem; }

    Secondly, you have a double loop using "for" and "GetFirst/GetNext". Use one or the other. You can also use "foreach":

    Outlook.Items items = folder.Items;
    
    //"for" loop - note it is 1 based
    for (int k = 1; k <= items.Count; k++)
    {
      OulookAppointment apt = items[k];
      ...
    }
    
    //foreach loop
    foreach (Outlook.Appointment apt in items)
    {
      ...
    }
    
    //GetFirst/GetNext loop
    (Outlook.Appointment apt = items.GetFirst();
    while (apt != null)
    {
      ..
      apt = items.GetNext();
    }


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

    Sunday, August 9, 2015 4:25 PM
  • Eugene,

       If I do the following as I think your suggesting I get a compilation error which I tried originally leaving me to the other options.  The error is "cannot apply indexing  with [] to expression of type 'Outlook.Items'. I also tried foreach
    and in both cases it complained of the lack of the enumerator. What is missing here? 

           ap = folder.Items[k] as Outlook.AppointmentItem;
    Sunday, August 9, 2015 5:33 PM
  • Hi Dmitry, the problem is I tried the foreach originally and as mentioned to Eugene above there is not enumerator available on the items object thus the problem. I may not be using the right assembly but here is the code I tried
    What assembly has the object model I need to do the foreach or items[k] reality?

       If I do the following as I think your suggesting I get a compilation error which I tried originally leaving me to the other options.  The error is "cannot apply indexing  with [] to expression of type 'Outlook.Items'. I also tried foreach

    and in both cases it complained of the lack of the enumerator. What is missing here? 

           ap = folder.Items[k] as Outlook.AppointmentItem;

    Sunday, August 9, 2015 5:39 PM
  • You need to get an instance of the Items class first and then on a separate line of code use the indexer property. Calling the mentioned line of code you get a new Items instance each time. Break the chain of calls first and work with the same instance of the Items class.
    Sunday, August 9, 2015 5:41 PM
  • Hi Eugene,

       That is because I posted the original code so you and Dmitry could see where the errors where. I am going to fix once I feel I understand what your saying. I will break the chain as you suggested. What is the rule of when to do the com release. Can you give me a couple lines of code to show me acquiring an object then releasing the reference on it.

    Thanks,

    Michael

    Sunday, August 9, 2015 5:41 PM
  • I think this is because I may be using AddInExpress which I am still evaluating through some article searching. That is the lack of the enumerator.
    Sunday, August 9, 2015 6:03 PM
  • I confirmed this. By using the following using clause it stopped the problem

    using Outlook1 = Microsoft.Office.Interop.Outlook;

    Sunday, August 9, 2015 6:18 PM
  • Have you tried the other two methods?

    Let me stress once again, do not use multiple dot notation. Cache the MAPIFolder.Items collection before entering the loop, then use it inside that loop instead of calling MAPIFolder.Items every time.

     

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

    Sunday, August 9, 2015 6:24 PM
  • Hi Dmitry,

       I have it working with the enumerator now. I need to know how to store a value in the folder object now and
       I can create UserDefinedProperties addition but it returns a UserDefineProperty and that does not seem to have a Value property. The UserProperty type does not exist off the folder object. So what do I do to set a custom value on a property?

    Thanks,

    Michael

    Sunday, August 9, 2015 8:35 PM
  • Folder.UserDefinedProperties is for storing property*definitions* so that they can be shown in folder views. The values come from actual items.

    If you want to store a custom property on a particular item, use Item.PropertyAccessor.SetProperty or Item.UserProperties.

    Folders (especially Exchange folders) do not generally allow to set custom properties. If you want folder-wide property, use a hidden (associated) message - see MAPIFolder.GetStorage.

    You can see existing hidden messages in a particular folder using OutlookSpy - click IMAPIFolder, go to the "Associated Contents" tab.


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


    Sunday, August 9, 2015 9:05 PM
  • Dmitry,

       Do you know of a sample project c# for Visual 2013 addin so I don't have to use AddIn Express?

    Thanks,

    Michael

    Sunday, August 9, 2015 9:15 PM
  • I thought you can still use the Outlook Object Model from Addin Express.

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

    Sunday, August 9, 2015 9:24 PM
  • You can but I mean that generates the scaffolding for you. The basic interfaces, the registration functions, etc there is an office outlook addin project in Visual Studio 2013 and wondering if there is a project example zip that uses this specific project. The addin express costs $.
    Sunday, August 9, 2015 10:24 PM
  • My updated coded is here. If you search for your name in the code you will see places I was wondering if it needed to release the com object. I updated with enumerator specific code and the double + dot's are taken care of. For the storage for the custom property I used a Dictionary<string, int> just to get it done faster.

            private void RecurseThroughFolders(Outlook1.MAPIFolder folder, Outlook1.Folders folders, Request request, bool skip, Dictionary<string, int> dLoop)
            {
                Outlook1.AppointmentItem ap = null;

                int ndx = 0;

                if (folder == null)
                {
                    return;
                }

                if (!skip)
                {

                    Outlook1.Items items = folder.Items;

                    for (int k = 1; k < items.Count; k++)
                    {
                        Appointment apcrm = new Appointment();
                        
                        ap = items[k] as Outlook1.AppointmentItem;

                        if (ap == null)
                        {
                            continue;
                        }

                        if (ap.Start < DateTime.Parse(request.StartDate) || ap.End > DateTime.Parse(request.EndDate + " 23:59:59"))
                        {
                            continue;
                        }

                        if (ap.UserProperties != null)
                        {
                            Outlook1.UserProperties userProperties = ap.UserProperties;
                            
                            Outlook1.UserProperty property = userProperties.Find("activityid", true);

                            if (property != null)
                            {
                                apcrm.ActivityId = property.Value;
                            }
                        }

                        apcrm.FolderId = ap.Parent.EntryID;
                        apcrm.EntryId = ap.EntryID;
                        apcrm.Describe = ap.Body;
                        apcrm.EventStart = ap.Start.ToShortDateString();
                        apcrm.EventEnd = ap.End.ToShortDateString();
                        apcrm.Subject = ap.Subject;
                        apcrm.StartTime = ap.Start.TimeOfDay.ToString();
                        apcrm.EndTime = ap.End.TimeOfDay.ToString();
                        apcrm.CreateDate = ap.CreationTime.ToString();
                        apcrm.LastModified = ap.LastModificationTime.ToString();
                        apcrm.PercentComplete = "0";
                        apcrm.ActivityId = "-1";
                        apcrm.ActivityType = "-1";
                        apcrm.SubActivityId = "-1";
                        apcrm.EntityId = "-1";
                        apcrm.EntityType = "-1";

                        if (ap.UserProperties != null)
                        {
                            Outlook1.UserProperties userProperties = ap.UserProperties;

                            Outlook1.UserProperty property = userProperties.Find("entityid", true);

                            if (property != null)
                            {
                                apcrm.EntityId = property.Value;
                            }

                            property = userProperties.Find("entitytype", true);

                            if (property != null)
                            {
                                apcrm.EntityType = property.Value;
                            }
                        }

                        if (ap.Importance == Outlook1.OlImportance.olImportanceHigh)
                        {
                            apcrm.Priority = "1";
                        }

                        if (ap.Importance == Outlook1.OlImportance.olImportanceNormal)
                        {
                            apcrm.Priority = "2";
                        }

                        if (ap.Importance == Outlook1.OlImportance.olImportanceLow)
                        {
                            apcrm.Priority = "3";
                        }

                        Outlook1.RecurrencePattern rp = ap.GetRecurrencePattern();

                        if (ap.IsRecurring)
                        {
                            apcrm.Duration = Convert.ToString(rp.Duration);
                            
                            apcrm.Occurrences = Convert.ToString(rp.Occurrences);
                            
                            apcrm.NoEndDate = rp.NoEndDate == true ? "1" : "0";

                            if (rp.RecurrenceType == Outlook1.OlRecurrenceType.olRecursDaily)
                            {
                                apcrm.Recurs = "1";
                            }

                            if (rp.RecurrenceType == Outlook1.OlRecurrenceType.olRecursWeekly)
                            {
                                apcrm.Recurs = "2";
                            }

                            if (rp.RecurrenceType == Outlook1.OlRecurrenceType.olRecursMonthly)
                            {
                                apcrm.Recurs = "3";
                            }

                            if (rp.RecurrenceType == Outlook1.OlRecurrenceType.olRecursYearly)
                            {
                                apcrm.Recurs = "4";
                            }

                            int toBase = 2;

                            rp.DayOfWeekMask = Outlook1.OlDaysOfWeek.olThursday;

                            string binary = Convert.ToString(Convert.ToInt32(rp.DayOfWeekMask), toBase);

                            binary = binary.PadLeft(8, '0');

                            if (!string.IsNullOrEmpty(binary))
                            {
                                apcrm.Sunday = "0";
                                apcrm.Monday = "0";
                                apcrm.Tuesday = "0";
                                apcrm.Wednesday = "0";
                                apcrm.Thursday = "0";
                                apcrm.Friday = "0";
                                apcrm.Saturday = "0";

                                string sbit = binary.Substring(0, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Sunday = "1";
                                }

                                sbit = binary.Substring(1, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Monday = "1";
                                }

                                sbit = binary.Substring(2, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Tuesday = "1";
                                }

                                sbit = binary.Substring(3, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Wednesday = "1";
                                }

                                sbit = binary.Substring(4, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Thursday = "1";
                                }

                                sbit = binary.Substring(5, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Friday = "1";
                                }

                                sbit = binary.Substring(6, 1);

                                if (sbit == "1")
                                {
                                    apcrm.Saturday = "1";
                                }
                            }

                            apcrm.RecursEvery = Convert.ToString(rp.Interval);

                            if (ap.ReminderMinutesBeforeStart > 0)
                            {
                                apcrm.RemindMe = "1";
                            }
                            else
                            {
                                apcrm.RemindMe = "0";
                            }

                            //not mapped
                            //task.SubActivityId = "";
                        }

                        Marshal.ReleaseComObject(rp);
                        Marshal.ReleaseComObject(ap);
                        
                        request.AppointmentList.Add(apcrm);

                    }

                    folders = folder.Folders;

                    //Dmitry Do I Need It Here?

                }

                if (folders.Count > 0)
                {
                    if (!dLoop.TryGetValue(folder.EntryID, out ndx))
                    {
                        ndx = 1;
                    }
                    else
                    {
                        ndx++;
                    }
                   
                    for (int i = ndx; i < folders.Count; i++)
                    {
                        folder = folders[i];
                        folders = folder.Folders;

                        //Dmitry Do I Need It Here? 
                             
                        dLoop[folder.EntryID] = i;
                        RecurseThroughFolders(folder, folders, request, false, dLoop);
                    }
                }
                else
                {
                    Outlook1.Folder folder1 = folders.Parent;

                    //Dmitry Do I Need It Here?

                    Outlook1.Folder folder2 = folder1.Parent;

                    //Dmitry Do I Need It Here?
                    
                    RecurseThroughFolders(folder, folder2.Folders, request, true, dLoop);
                }
            }

    Sunday, August 9, 2015 10:28 PM
  • So after processing a folder, you are trying to go up the level? Why? This is usually done from top to bottom:

    foreach (Outlook.MAPIFolder topFolder in Application.Session.Folders)
    {
      processSubfolder(topFolder);
    }
    
    ...
    
    private void ProcessFolder (Outlook.MAPIFolder folder)
    {
      //process items
      if (folder.DefaultItemType == Outlook.OlItemType.olAppointmentItem)
      {
        foreach (Outlook.AppointmentItem apt in folder.Items)
        {
            ..
        }
      }
      //process subfolders
      foreach (Outlook.MAPIFolder childFolder in folder.Folders)
      {
        processSubfolder(childFolder);
      }
    }
    


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

    Sunday, August 9, 2015 11:11 PM
  • Hi Dmitry,

    This is cleaner. I did not know the object model that well so I wanted to control the cycle better. The reason I did this was because at first I did not have the enumerator but then when found out about the conflict with the addin express name space I still kept the indexes but recursively i had regain their state which is why I went up but with the foreach there is not need to do this thus the solution is much cleaner. One hopeful last item. I noticed in the code you iterated through a list of top level folders. Is there a root folder such that what I have below would work or do I have to iterate through the top level folders.

    Thanks,

    Michael

    Sunday, August 9, 2015 11:49 PM
  • Namespace.Folders returns a collection of all top level folders of all stores in the profile - e.g. if you have Exchange mailbox store, Public Folders and a PST store,  Namespace.Folders will contain 3 folders from each of these stores.

    You might want to limit yourself to the default store only if you do not want to process secondary store or if doing so can be expensive (e.g. in case of PF store you can have thousands of folders and none of them would be cached).The top level folder of the primary mailbox can be retrived from

    Namespace.GetDefaultFolder(olFolderInbox).Parent.


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

    Monday, August 10, 2015 12:03 AM
  • Its been quite a while since I touched native COM in C++ but with the interop isn't there a managed wrapper around the Com interface that disposes of the object implicitly if I don't or do I always have to do that? Is there any garbage collection that would do that lets say if I did not. Additionally in the foreach below do I need to cleanup these top level objects as well through Marshal.ReleaseComObject call?

    Thanks for the great solution.

                foreach (Outlook1.MAPIFolder topFolder in application.Session.Folders)
                {
                    RecurseThroughFolders(topFolder);
                }

    Monday, August 10, 2015 12:06 AM
  • Not in C# - everything will be cleaned for you. Note that .Net keeps all collection items referenced for the foreach loops until the loop exits. Use a "for" loop instead and call Marshal.ReleaseComObject() if you run out of RPC channels in the online Exchange mode.


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

    Monday, August 10, 2015 12:47 AM
  • Dmitry,

       When I add an appointment from my CRM product not already in Outlook what is the recommended folder to add the appointment to. Is there a default folder that has a default calendar I can use if that is what you recommend.

    Thanks,

    Michael

    Monday, August 10, 2015 1:26 AM
  • Sorry for the plethora of questions.

    So when Eugene said to use the release function was he saying that as a method that may be a must have which it appears he was saying based on what you said to me that cleanup will take care of it rather than a necessity. He may have said it because its just a good thing to do just in case what you were saying about RPC connections becomes a reality.



    Monday, August 10, 2015 1:59 AM
  • yes, Namespace.GetDefaultFolder(olFolderCalendar) will return the default Calendar folder.

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

    Monday, August 10, 2015 3:20 AM
  • It is not just a good thing, releasing underlying COM objects in a timely manner allows to avoid known issues when dealing with OOM. 
    Monday, August 10, 2015 12:41 PM
  • agreed!

    Monday, August 10, 2015 1:02 PM
  • And you may also consider using VSTO which is included in the paid editions of Visual Studio for developing Outlook add-ins. See Walkthrough: Creating Your First VSTO Add-In for Outlook to get started quickly.
    Monday, August 10, 2015 1:12 PM
  • Hi Eugene, thanks again I did get your other links.
    Monday, August 10, 2015 3:43 PM