2016-04-24 3 views
0

öffnen Ich habe für das Kopieren von Kontakten von einem Ordner zum anderen eine einfache Outlook-Add-in erstellt. (~ 5000 Kontakte)Outlook-Add-In-Abstürze oder Serveradministrator die Anzahl der Elemente ist begrenzt können Sie gleichzeitig

Warum Ich brauche das? Es gibt eine seltsame Möglichkeit, ein öffentliches Adressbuch zu erstellen, wie beschrieben here.

Warum also nicht alle Kontakte in den öffentlichen Ordner kopieren? Ich möchte, dass mein Team ein gemeinsames Adressbuch mit meinen Kontakten hat, aber nur mit Fullname und E-Mails als Informationen.

Ich habe eine Symbolleiste mit zwei Schaltflächen hinzugefügt. Wählen Sie Ordner und Synchronisieren.

Mein Problem ist, dass, wenn die Synchronisation nach einer Weile läuft ich

Serveradministrator beschränkt hat die Anzahl der Elemente erhalten Sie gleichzeitig öffnen können. Versuchen Sie, Nachrichten zu schließen, die Sie geöffnet haben, oder entfernen Sie Anhänge und Bilder von nicht gesendeten Nachrichten, die Sie verfassen.

Ich verwendete Marshal.ReleaseComObject in jedem Objekt, versuchte, etwas Verzögerung zwischen Add hinzuzufügen. Aber immer noch den gleichen Fehler.

Dann fand ich einen Beitrag hier in Stackoverflow sagen GC.Collect hinzuzufügen, der den Fehler gestoppt oben, aber die Outlook immer Abstürze am Ende der Synchronisier- und manchmal in der Mitte davon.

Jede Hilfe wird geschätzt.

Synchronize-Code

private Task SynchronizeContactsSync() 
    { 
     return Task.Run(async() => 
     { 
      if (!synchronizing) 
      { 
       synchronizing = true; 

       Outlook.Folder toFolder = null; 
       Outlook.Folder fromFolder = null; 
       try 
       { 
        if (!string.IsNullOrWhiteSpace(tEntryID) && !string.IsNullOrWhiteSpace(tStoreID) && 
        !string.IsNullOrWhiteSpace(fStoreID) && !string.IsNullOrWhiteSpace(tEntryID)) 
        { 
         toFolder = Application.Session.GetFolderFromID(tEntryID, tStoreID) as Outlook.Folder; 
         fromFolder = Application.Session.GetFolderFromID(fEntryID, fStoreID) as Outlook.Folder; 
        } 

        if (toFolder != null && fromFolder != null) 
        { 
         toFolder.InAppFolderSyncObject = false; 
         int currentItem = 0; 


         int itemCount = fromFolder.Items.Count; 

         //I dont want to use foreach because it keeps reference of each object until is done 
         //I cast it to list because i cant use for statement with fromFolder.Items 

         List<Outlook.ContactItem> items = fromFolder.Items.Cast<Outlook.ContactItem>().ToList(); ; 

         for (int i = 0; i < items.Count; i++) 
         { 

          //await Task.Delay(33); 
          await addContactSync(items[i], toFolder); 
          if (items[i] != null) Marshal.ReleaseComObject(items[i]); 
          GC.Collect(); 
          GC.WaitForPendingFinalizers(); 
          GC.Collect(); 
          GC.WaitForPendingFinalizers(); 
          currentItem++; 
          syncText = "Synchronize progress " + currentItem + " of " + itemCount; 
         } 

         synchronizing = false; 
         syncText = "No Synchronize in progress"; 



        } 
        MessageBox.Show("Done.", "Synchronize", MessageBoxButtons.OK, MessageBoxIcon.Information); 
        if (toFolder != null) Marshal.ReleaseComObject(toFolder); 
        if (fromFolder != null) Marshal.ReleaseComObject(fromFolder); 
        toFolder.InAppFolderSyncObject = true; 
       } 
       catch (Exception ex) 
       { 
        if (toFolder != null) Marshal.ReleaseComObject(toFolder); 
        if (fromFolder != null) Marshal.ReleaseComObject(fromFolder); 
        toFolder.InAppFolderSyncObject = true; 
        synchronizing = false; 
        syncText = "No Synchronize in progress"; 
        MessageBox.Show(ex.Message, "Synchronize", MessageBoxButtons.OK, MessageBoxIcon.Information); 
       } 
      } 
      else 
      { 
       MessageBox.Show("Check you settings or please wait for the synchronization to finish.", "Synchronize", MessageBoxButtons.OK, MessageBoxIcon.Information); 
      } 
     }); 
    } 



    private Task addContactSync(Outlook.ContactItem item, Outlook.Folder toFolder) 
    { 
     return Task.Run(() => 
     { 
      try 
      { 

       if (!string.IsNullOrWhiteSpace(item.Email1Address)) 
       { 
        string filter = "[FullName] = '" + item.FullName + "'";// "[NickName] = '" + item.NickName + "' or [Email1Address] = '" + item.Email1Address + "' or 

        Outlook.ContactItem matches = (Outlook.ContactItem)toFolder.Items.Find(filter); 
        if (matches == null) 
        { 
         Outlook.ContactItem contact = toFolder.Items.Add(Outlook.OlItemType.olContactItem); 
         contact.FullName = item.FullName; 
         contact.NickName = item.NickName; 
         contact.Email1Address = item.Email1Address; 
         contact.Email2Address = item.Email2Address; 
         contact.Save(); 
         Marshal.ReleaseComObject(contact); 
         itemSyncCount++; 
         lastItemSync = DateTime.Now; 
        } 
        else 
        { 
         matches.Email1Address = item.Email1Address; 
         matches.Email2Address = item.Email2Address; 
         matches.Save(); 
         itemSyncCount++; 
         lastItemSync = DateTime.Now; 
        } 

        if (item != null) Marshal.ReleaseComObject(item); 
        if (matches != null) Marshal.ReleaseComObject(matches); 

       } 
      } 
      catch (Exception ex) 
      { 
       Marshal.ReleaseComObject(item); 
       MessageBox.Show(ex.Message, "Contact", MessageBoxButtons.OK, MessageBoxIcon.Information); 
      } 
     }); 
    } 

Antwort

0

Verwenden Sie keine LINQ Aussagen nicht gegen Outlook Sammlungen. Oder Sie werden in solche Situationen hineinfallen. Beispiel:

List<Outlook.ContactItem> items = fromFolder.Items.Cast<Outlook.ContactItem>().ToList(); ; 

Die Codezeile erstellt ein neues COM-Objekt für jedes Element in dem Ordner gleichzeitig. Stattdessen können Sie über alle Elemente in dem Ordner in der für Schleife durchlaufen und Objekte mithilfe der Marshal.ReleaseComObject-Methode sofort freigeben.

for (int i = 0; i < items.Count; i++) 
{ 
    object item = items[i]; 
    ... 
    Marshal.ReleaseComObject(item); item = null; 
} 

Verwenden System.Runtime.InteropServices.Marshal.ReleaseComObject ein Outlook-Objekt freizugeben, wenn Sie es nicht mehr benötigen. Dies ist besonders wichtig, wenn Ihr Add-In versucht, mehr als 256 Outlook-Elemente in einer Auflistung aufzuzählen, die auf einem Microsoft Exchange Server gespeichert ist. Wenn Sie diese Objekte nicht rechtzeitig freigeben, können Sie die von Exchange festgelegte Grenze für die maximale Anzahl der gleichzeitig geöffneten Elemente erreichen. Setzen Sie dann in Visual Basic eine Variable auf Nothing (null in C#), um den Verweis auf das Objekt freizugeben. Lesen Sie mehr dazu im Artikel Systematically Releasing Objects.

+0

Ich kann 'tun for (int i = 0; i Stamos

Verwandte Themen