Невозможно удалить более 400 контактов из Outlook с помощью Office Interop - PullRequest
0 голосов
/ 06 мая 2019

У меня есть этот код для удаления всех контактов из Microsoft Outlook с определенным пользовательским свойством:

public void PurgePTSContacts(ref long rlCount)
{
    int iLastPercent = 0;
    rlCount = 0;

    try
    {

        // Get the MAPI namespace object (not sure exactly what this is)
        Outlook.NameSpace MAPI = _OutlookApp.GetNamespace("MAPI");
        if (MAPI != null)
        {
            // Now get the default Outlook Contacts folder
            Outlook.MAPIFolder oFolder = MAPI.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts);
            if (oFolder != null)
            {
                // Ensure it is a calendar folder.  This test is not strictly required.
                if (oFolder.DefaultItemType == Outlook.OlItemType.olContactItem)
                {
                    // Get the collect of items from the calendar folder
                    Outlook.Items oFolderItems = oFolder.Items;
                    if (oFolderItems != null)
                    {
                        int iNumItems = oFolderItems.Count;

                        // Progress to do

                        int iItem = 0;
                        foreach (object oItem in oFolderItems)
                        {
                            iItem++;

                            if(oItem is Outlook.ContactItem )
                            {
                                Outlook.ContactItem oContact = (oItem as Outlook.ContactItem);

                                int iPercent = ((iNumItems - iItem) + 1) * 100 / iNumItems;
                                if (iPercent >= iLastPercent + 5 || iPercent == 100)
                                {
                                    iLastPercent = iPercent;
                                    // Show progress
                                }

                                Outlook.UserProperties oContactDetails = oContact.UserProperties;
                                if (oContactDetails != null)
                                {
                                    if (oContactDetails.Find("xxxxx") != null)
                                    {
                                        oContact.Delete();
                                        rlCount++;
                                    }
                                }

                                oContact = null;
                            }
                        }
                    }
                }
            }
        }
    }
    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }
}

Теперь, что я не понимаю, так это то, что когда я импортирую контакты, их 428. Но когда я удаляю контакты, это делает чуть более 200. Затем я должен повторно вызвать мой метод PurgePTSContacts, и он удаляет еще немного.

С каждым последующим вызовом все меньше удаляется, пока не станет 0.

Почему я не могу удалить все 400x за один вызов функции?

1 Ответ

3 голосов
/ 06 мая 2019

Не используйте foreach при изменении коллекции - используйте нисходящий цикл:

for (int i = FolderItems.Count; i >= 1; i--)
{
  object oItem = FolderItems[i];
  Outlook.ContactItem oContact = (oItem as Outlook.ContactItem);
  if (oContact  != null)
  {
    ...
    Marshal.ReleaseComObject(oContact);
  }
  Marshal.ReleaseComObject(oItem);
}

ОБНОВЛЕНИЕ .Для запроса OP, пример, который показывает, как удалить все элементы в папке, используя Погашение :

RDOSession session = new RDOSession();
session.MAPIOBJECT = MAPI.MAPIOBJECT; //an instance of the Namespace object from your snippet above
RDOFolder rFolder = session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderContacts); //or you can use RDOSession.GetFolderFromID if you already have an Outlook.MAPIFolder
rFoldder.EmptyFolder ();

Если вы хотите удалить только контакты (но не списки рассылки), вы можетесначала получите их идентификаторы записей, используя RDOFolder.Items.MAPITable.ExecSQL("SELECT EntryID from Folder where MessageClass LIKE 'IPM.Contact%' ") (ExecSQL возвращает экземпляр ADODB.Recordset COM-объекта), используйте его для создания массива идентификаторов записей и передайте его RDOFolder.Items.RemoveMultiple().

.экземпляр объекта RDOSession , вы также можете использовать класс RedemptionLoader , если вы не хотите регистрировать redemption.dll в реестре с помощью regsvr32.exe (вы можете просто поместить выкуп.dll вместе с вашим исполняемым файлом).

...