Outlook 16.0 Not Responding after moving 1000 emails

Add-in Express™ Support Service
That's what is more important than anything else

Outlook 16.0 Not Responding after moving 1000 emails
 
David@WizardsEnterprise.com




Posts: 39
Joined: 2015-11-20
In outlook I have a gmail IMAP account. With VB.net I am executing code that loops thru all emails in Folder1. The loop is executed by getting the email item count of the folder and then looping thru the item index starting with the item count with a -1 step. For each iteration of the loop the current MailItem details are saved to sql server and then the email is moved into Folder2.

The problem is that outlook goes non-responsive after about 1000 emails. The behavior is consistent no matter how I try to modify the code. My code is not throwing any errors at all and when I debug I can see that my code is left waiting on the line where it assigns then next MailItem to the comObject.

I need to process large volumes of emails with this code, in excess of 20,000. Any idea why outlook is hanging but my code is not throwing any errors? Thank you.
Posted 29 May, 2019 09:22:38 Top
Andrei Smolin


Add-in Express team


Posts: 18829
Joined: 2006-05-11
Hello David,

This may be caused by the implementation of the corresponding message store. Anyway, using the Outlook object model or doing some serious calculations on the main thread must show itself somehow. Since you can't avoid using the main thread, you should create a mechanism sharing the CPU between your code and Outlook needs. Whether your code works or not, Outlook must handle user activity and its business logic. When your code takes all CPU time or other resource(s) away, you see the issue.

I suppose, one of the resources that you might exhaust is the number of data connections (don't know if these even exist in case of IMAP) opened simultaneously. In case of Exchange, these connections are created whenever you create a COM object e.g. for an email item. The limit is reached soon if you do not release COM objects created in your code. How the COM server (in your case, this is the message store and/or Outlook) reacts to this depends on its implementation (= we can't know this). To prevent these issue, we strongly recommend releasing all COM objects that your code crates; please check section Releasing COM Objects at https://www.add-in-express.com/docs/net-office-tips.php#releasing.


Andrei Smolin
Add-in Express Team Leader
Posted 30 May, 2019 07:08:12 Top
David Wisniewski




Posts: 39
Joined: 2015-11-20
Hi Andrei. Thank you for your help, I have learned a lot over the years here with Add-in Express and I love it. I followed your advice and you were right that I was not properly handling a comObject. I've gotten pretty good with it thanks to all the help I've received here but I still tend to overlook things sometimes. So after resolving that issue Outlook no longer hangs after 1000 emails, but I've found another issue that I have specifically relating to releasing comObjects and was wondering if you can help me, as I also believe this will help others here with releasing comObjects that are created WithEvents. What I've done is isolate the problem code from my Add-in and put it into a sample Windows Forms Application to test just it without any other interference. In the code I am connecting to an Outlook SyncObject WithEvents so that I can force the IMAP folders to sync with the server and receive notification when the sync is complete so that I can then safely quit outlook. The problem is that after I release the comObjects and tell outlook to quit, it will not quit. I'm pretty sure that the issue is with my handling of the Outlook.SyncObejct.SyncEnd event because if I remove the WithEvents and event handling from the code and just force the sync object to start syncing and then release comObjects and quit outlook, outlook actually quits. Can you use this sample code to show me how to properly handle this comObject so that I can tell Outlook to quit and it actually quits? Thank you again so much for your help. Sample Code below:

Imports Marshal = System.Runtime.InteropServices.Marshal
Imports Outlook = Microsoft.Office.Interop.Outlook
Public Class Form1
    'Start outlook 2016
    Private comOutlook As Outlook.Application = New Outlook.Application
    'connect to namespace
    Private comNSMapi As Outlook.NameSpace = comOutlook.GetNamespace("MAPI")
    'handle syncobjects collection
    Private comSyncObjects As Outlook.SyncObjects = comNSMapi.SyncObjects
    'create syncobject with eventhandling to alert when sync is complete
    Private WithEvents comEvtSyncObj As Outlook.SyncObject = comSyncObjects.Item(1)

    'handle syncend event for syncobject
    Private Sub EvtSyncEnd() Handles comEvtSyncObj.SyncEnd
        MsgBox("Sync End")
        'release comobjects
        ReleaseCOM(comEvtSyncObj)
        ReleaseCOM(comSyncObjects)
        ReleaseCOM(comNSMapi)
        comOutlook.Quit()
        ReleaseCOM(comOutlook)

        'now outlook should close, but it does not, which leads me to believe that there
        'is still a handle to a comobject of some sort but I can't see where.
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        comEvtSyncObj.Start()
    End Sub

    Private Sub ReleaseCOM(ByRef comObject As Object)
        Marshal.ReleaseComObject(comObject)
        comObject = Nothing
    End Sub
End Class
Posted 30 May, 2019 10:19:08 Top
David Wisniewski




Posts: 39
Joined: 2015-11-20
So I solved the problem, and hopefully others can learn from this. Maybe you can add this to your blog post about properly handling comObjects so that others will not have to learn the hard way? The problem was that my SyncObject had an event handler attached to it, so when I released the SyncObject it did not actually release because the event handler was still holding on listening for the event. So when I added a line to remove the handler before releasing the objects, outlook immediately quit as instructed. See revised code below:

Imports Marshal = System.Runtime.InteropServices.Marshal
Imports Outlook = Microsoft.Office.Interop.Outlook
Public Class Form1
    'Start outlook 2016
    Private comOutlook As Outlook.Application = New Outlook.Application
    'connect to namespace
    Private comNSMapi As Outlook.NameSpace = comOutlook.GetNamespace("MAPI")
    'handle syncobjects collection
    Private comSyncObjects As Outlook.SyncObjects = comNSMapi.SyncObjects
    'create syncobject with eventhandling to alert when sync is complete
    Private WithEvents comEvtSyncObj As Outlook.SyncObject = comSyncObjects.Item(1)

    'handle syncend event for syncobject
    Private Sub EvtSyncEnd() Handles comEvtSyncObj.SyncEnd
        'need to remove the event handler before releasing the comobject or 
        'outlook will not quit because the comobject doesn't actually release
        RemoveHandler comEvtSyncObj.SyncEnd, AddressOf EvtSyncEnd
        'release comobjects
        ReleaseCOM(comEvtSyncObj)
        ReleaseCOM(comSyncObjects)
        ReleaseCOM(comNSMapi)
        comOutlook.Quit()
        ReleaseCOM(comOutlook)

        MsgBox("Sync End")
        'outlook now quits successfully... lesson learned for the day is that
        'comobjects with event handlers must have the event handler removed before
        'releasing!
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        comEvtSyncObj.Start()
    End Sub

    Private Sub ReleaseCOM(ByRef comObject As Object)
        Marshal.ReleaseComObject(comObject)
        comObject = Nothing
    End Sub
End Class
Posted 30 May, 2019 10:49:00 Top
Andrei Smolin


Add-in Express team


Posts: 18829
Joined: 2006-05-11
David, you've noted something really important! You are absolutely right: before we release a COM object providing events, we should disconnect from the events first.

Thank you very much!


Andrei Smolin
Add-in Express Team Leader
Posted 31 May, 2019 05:12:54 Top