![]() |
If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. |
|
|
Thread Tools | Search this Thread | Display Modes |
|
#1
|
|||
|
|||
![]()
Hi,
I would appreciate any ideas about avoiding the following exception: ---- [ERR] System.Runtime.InteropServices.COMException (0x80040119): One or more items cannot be moved because items you previously moved are still being processed by the server. [ERR] at Microsoft.Office.Interop.Outlook._MailItem.Delete( ) ---- I am getting this exception when deleting the first email (NB: I am starting deletion from the last item in MAPIFolder.Items) in Sent Item folder right after deleting all emails in Inbox is finished. Usually this problem doesn't happen right after I am starting my automation, but after it happens once it will happen in all subsequent runs. Also, it never happens with Outlook2k3, but it does with Outlook2k7. Thank you, --Leon. |
#2
|
|||
|
|||
![]()
Show the code loop you're using.
You are releasing all of your objects? Often due to GC latency you will need to call Marshal.ReleaseComObject() or Marshal.FinalReleaseComObject(). Setting the objects to null isn't sufficient. -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "LeonKh" wrote in message ... Hi, I would appreciate any ideas about avoiding the following exception: ---- [ERR] System.Runtime.InteropServices.COMException (0x80040119): One or more items cannot be moved because items you previously moved are still being processed by the server. [ERR] at Microsoft.Office.Interop.Outlook._MailItem.Delete( ) ---- I am getting this exception when deleting the first email (NB: I am starting deletion from the last item in MAPIFolder.Items) in Sent Item folder right after deleting all emails in Inbox is finished. Usually this problem doesn't happen right after I am starting my automation, but after it happens once it will happen in all subsequent runs. Also, it never happens with Outlook2k3, but it does with Outlook2k7. Thank you, --Leon. |
#3
|
|||
|
|||
![]()
Thank you for the reply! Clean exit of Outlook is such a struggle. It looks
like this exception starts happening together with a warning in the right lower corner of Outlook window: "A data file did not close properly the last time it was used and is being checked for problems. performance might be affected while the check is in progress." Here the method I use, which has some debugging/troubleshooting parts: public void DeleteAllEmailsInFolder(MAPIFolder mpf) { Trace.TraceInformation("Deleting items in folder \"{0}\"", mpf.FullFolderPath); // Increments delay between successive deletions, in millisecs. int timeStep = 100; // Limits the maximum delay, in millisecs. int timeOut = 10000; // Logon. NameSpace outlookNameSpace = myOutlookApp.GetNamespace("MAPI"); // Determine how many items in folder. int totalNumberOfItemsInFolderToDelete = mpf.Items.Count; if (totalNumberOfItemsInFolderToDelete 0) { int mCounter = 0; // deleted mail item counter int rCounter = 0; // deleted report item counter int aCounter = 0; // deleted appointment item counter // Iterate thru all items and call the delete method on emails. for (int i = totalNumberOfItemsInFolderToDelete; i = 1; i--) { Object Item = mpf.Items[i]; if (Information.TypeName(Item) == "MailItem") { int beforeDelete = mpf.Items.Count; MailItem outlookMailItem = (MailItem)Item; outlookMailItem.Delete(); //@ A delay for processing deletion int timer = 0; while (mpf.Items.Count != (beforeDelete - 1)) { Thread.Sleep(timeStep); timer += timeStep; if (timer = timeOut) { Trace.TraceError( "mDeletion was not completed within " + "{0} millisecs.", timeOut); break; } } if (timer timeOut) { Trace.TraceInformation( "mDeletion completed within {0} millisecs.", timer); } mCounter++; continue; } if (Information.TypeName(Item) == "ReportItem") { int beforeDelete = mpf.Items.Count; ReportItem outlookReportItem = (ReportItem)Item; outlookReportItem.Delete(); //@ A delay for processing deletion int timer = 0; while (mpf.Items.Count != (beforeDelete - 1)) { Thread.Sleep(timeStep); timer += timeStep; if (timer = timeOut) { Trace.TraceError( "rDeletion was not completed within " + "{0} millisecs.", timeOut); break; } } if (timer timeOut) { Trace.TraceInformation( "rDeletion completed within {0} millisecs.", timer); } rCounter++; continue; } if (Information.TypeName(Item) == "AppointmentItem") { int beforeDelete = mpf.Items.Count; AppointmentItem outlookAppointmentItem = (AppointmentItem)Item; outlookAppointmentItem.Delete(); //@ A delay for processing deletion int timer = 0; while (mpf.Items.Count != (beforeDelete - 1)) { Thread.Sleep(timeStep); timer += timeStep; if (timer = timeOut) { Trace.TraceError( "aDeletion was not completed within " + "{0} millisecs.", timeOut); break; } } if (timer timeOut) { Trace.TraceInformation( "aDeletion completed within {0} millisecs.", timer); } aCounter++; } } int totalDeleted = mCounter + rCounter + aCounter; Trace.TraceInformation("{0} items have been deleted in " + "\"{1}\" folder.", totalDeleted, mpf.FullFolderPath); } else { Trace.TraceInformation("There are no items to " + "delete in \"{0}\"", mpf.FullFolderPath); } } |
#4
|
|||
|
|||
![]()
One of the problems I see are lots of usages that will create internal
objects that can't be explicitly released. For example something as simple as this: int totalNumberOfItemsInFolderToDelete = mpf.Items.Count; That creates an internal object for mpf.Items. A better approach that gives you more control over lifetime is to use this: Outlook.Items myItems = mpf.Items; int totalNumberOfItemsInFolderToDelete = myItems.Count; That allows you to release myItems explicitly when the time comes. Same thing for any other object that uses compound dot operators. Within the loop something like this is another example: Object Item = mpf.Items[i]; Each loop pass not only creates the internal object for mpf.Items, but it also creates a new instance of Item. That could be declared outside the loop as Object Item = null; If declared within the loop, without compound dot operators, that would be a candidate for calling Marshal.ReleaseComObject(). Otherwise I'd just null that object in each loop pass. Go through the code with these things in mind and see if it makes a difference. -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "LeonKh" wrote in message ...[i] Thank you for the reply! Clean exit of Outlook is such a struggle. It looks like this exception starts happening together with a warning in the right lower corner of Outlook window: "A data file did not close properly the last time it was used and is being checked for problems. performance might be affected while the check is in progress." Here the method I use, which has some debugging/troubleshooting parts: public void DeleteAllEmailsInFolder(MAPIFolder mpf) { Trace.TraceInformation("Deleting items in folder \"{0}\"", mpf.FullFolderPath); // Increments delay between successive deletions, in millisecs. int timeStep = 100; // Limits the maximum delay, in millisecs. int timeOut = 10000; // Logon. NameSpace outlookNameSpace = myOutlookApp.GetNamespace("MAPI"); // Determine how many items in folder. int totalNumberOfItemsInFolderToDelete = mpf.Items.Count; if (totalNumberOfItemsInFolderToDelete 0) { int mCounter = 0; // deleted mail item counter int rCounter = 0; // deleted report item counter int aCounter = 0; // deleted appointment item counter // Iterate thru all items and call the delete method on emails. for (int i = totalNumberOfItemsInFolderToDelete; i = 1; i--) { Object Item = mpf.Items; if (Information.TypeName(Item) == "MailItem") { int beforeDelete = mpf.Items.Count; MailItem outlookMailItem = (MailItem)Item; outlookMailItem.Delete(); //@ A delay for processing deletion int timer = 0; while (mpf.Items.Count != (beforeDelete - 1)) { Thread.Sleep(timeStep); timer += timeStep; if (timer = timeOut) { Trace.TraceError( "mDeletion was not completed within " + "{0} millisecs.", timeOut); break; } } if (timer timeOut) { Trace.TraceInformation( "mDeletion completed within {0} millisecs.", timer); } mCounter++; continue; } if (Information.TypeName(Item) == "ReportItem") { int beforeDelete = mpf.Items.Count; ReportItem outlookReportItem = (ReportItem)Item; outlookReportItem.Delete(); //@ A delay for processing deletion int timer = 0; while (mpf.Items.Count != (beforeDelete - 1)) { Thread.Sleep(timeStep); timer += timeStep; if (timer = timeOut) { Trace.TraceError( "rDeletion was not completed within " + "{0} millisecs.", timeOut); break; } } if (timer timeOut) { Trace.TraceInformation( "rDeletion completed within {0} millisecs.", timer); } rCounter++; continue; } if (Information.TypeName(Item) == "AppointmentItem") { int beforeDelete = mpf.Items.Count; AppointmentItem outlookAppointmentItem = (AppointmentItem)Item; outlookAppointmentItem.Delete(); //@ A delay for processing deletion int timer = 0; while (mpf.Items.Count != (beforeDelete - 1)) { Thread.Sleep(timeStep); timer += timeStep; if (timer = timeOut) { Trace.TraceError( "aDeletion was not completed within " + "{0} millisecs.", timeOut); break; } } if (timer timeOut) { Trace.TraceInformation( "aDeletion completed within {0} millisecs.", timer); } aCounter++; } } int totalDeleted = mCounter + rCounter + aCounter; Trace.TraceInformation("{0} items have been deleted in " + "\"{1}\" folder.", totalDeleted, mpf.FullFolderPath); } else { Trace.TraceInformation("There are no items to " + "delete in \"{0}\"", mpf.FullFolderPath); } } |
#5
|
|||
|
|||
![]()
It looks like moving declarations out of the loop did help. So far the
automation completed about 10 runs without exceptions. Will let it go overnight. Thank you! |
#6
|
|||
|
|||
![]()
Speaking about releasing objects, what do you think about this approach?
http://blogs.msdn.com/eric_carter/ar...10/240568.aspx |
#7
|
|||
|
|||
![]()
What Eric was blogging about is more a problem with Outlook 2003 and earlier
than with Outlook 2007. It's known as the Catch-22 bug, Outlook won't close if you have objects in scope but how to know to release those objects? The Outlook team did a lot of work in Outlook 2007 to make sure OnDisconnection() always fires as a signal to release the Outlook objects. However, most of us do use Inspector and Explorer wrappers and check for the Close() event on each, then check for any existing instances of those objects. When the last Explorer or Inspector is closing that's the signal to release everything. I've been using variations of that approach since the Outlook 2000 beta, and my public templates from my Outlook 2007 book have implementations of similar wrappers and checks for closing. I also agree with Eric about the importance of shimming managed code shared addins, and the possible hazards of calling the Marshal methods of releasing COM objects. When you do that you release the RCW for that object and it's global to that AppDomain. For example, a MailItem object is instantiated in one class and passed to another. The second class calls Marshal.ReleaseComObject() on the MailItem. When the first class tries to do something then with that mail item you'll get a COM exception since the RCW was released for the object even though released on the copy in class 2. So you have to call those methods with care, but there are times you do need to do so. You just have to be aware of all references to those objects globally in your code and where you need to maintain the references and where you don't. Some times in a loop people use a construct like this: for (int i = 1; i itemCount; i++) { Outlook.MailItem foo = groupSelection[i]; // do something } That will create a new object each pass through the for loop. In a case like that where the foo object is local to the loop calling Marshal.ReleaseComObject() will affect only that instance of the object. Declaring foo outside of the loop just sets the object to a new value in each loop pass. Calling Marshal.ReleaseComObject() in that case within the loop will fire exceptions on the next loop pass since the RCW was released for foo and it's never instantiated as a new object again. So you really have to study and understand your code, and always use a shimmed approach to maintain your own AppDomain. -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "LeonKh" wrote in message ... Speaking about releasing objects, what do you think about this approach? http://blogs.msdn.com/eric_carter/ar...10/240568.aspx |
#8
|
|||
|
|||
![]()
I see. Definitely will get your book. Maybe it would be possible for somebody
experienced like you to go through our code (less than 1000 lines, I would say) and guide me while refactoring it? It would be a great way for me to learn. |
#9
|
|||
|
|||
![]()
I do consulting work like that, but here's not really the place to discuss
that. If you're interested in having me consult on your code ping me off list. -- Ken Slovak [MVP - Outlook] http://www.slovaktech.com Author: Professional Programming Outlook 2007. Reminder Manager, Extended Reminders, Attachment Options. http://www.slovaktech.com/products.htm "LeonKh" wrote in message ... I see. Definitely will get your book. Maybe it would be possible for somebody experienced like you to go through our code (less than 1000 lines, I would say) and guide me while refactoring it? It would be a great way for me to learn. |
Thread Tools | Search this Thread |
Display Modes | |
|
|
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
COMException saving contact picture | Battistaar | Outlook - Using Forms | 3 | March 4th 09 02:53 AM |
Issues with COMException | NateG | Outlook and VBA | 1 | June 17th 08 02:36 PM |
COMException | Jennifer | Outlook and VBA | 11 | April 23rd 07 04:46 PM |
Delete MailItem | j | Add-ins for Outlook | 5 | January 25th 07 06:47 PM |
verify and delete mailitem | Joanne | Outlook and VBA | 8 | June 13th 06 11:38 PM |