none
Outlook Automation Server dies after displaying MailItem RRS feed

  • Question

  • Greetings to all.

    I work on a legacy app, built in VB6.  Part of the app allows the user to create and send emails via their email provider (generally including attachments).  This has been working well for quite some time, but now we are seeing issues in Outlook 2007 and 2010.

    Essentially we are encountering two issues now:  first is that the new MailItem is created and "sent", but if the user does not have Outlook actively open (outside our automation calls), then the email just sits in the outbox until the user actually opens their Outlook, at which time the email actually sends.  Second, and more troubling, we are now seeing in both Outlook 2007 and 2010 that once the ".display" method is called on the MailItem, when control returns to our automation code, Outlook is dead.  The objects are still instantiated, but any attempt to access any properties or execute any methods result in errors along the lines of "the remote server machine does not exist or is unavailable".

    If we do not call the ".display" method, and use the ".send" method in automation code, everything works fine, including the email getting sent immediately, regardless whether Outlook is open or not.

    I have tested with simple code in both VB6 (legacy) and VB.Net with the same results.

    We are using late binding to the OOM since we have to allow for customers that essentially have all supported versions of Outlook.

    I would appreciate any ideas anyone has about (a) why the outlook objects are dying when the ".display" method is used and\or (b) why ".send" in automation code allows the email to be delivered, but relying on the "send" button on the actual Outlook MailItem leaves the email in the Outbox (perhaps it has something to do with Outlook objects dying?).

    Thanks in advance.

    VB6 Sample:

    Private Sub DoCleanEmailTest()
        Dim i As Integer
        Dim iVer As Integer
        Dim sVer As String
        Dim intSleepTime As Integer
        Dim ol As Object
        Dim ns As Object
        Dim newmail As Object
       
        On Local Error Resume Next
        Err.Clear
       
        If ol Is Nothing Then
            Set ol = CreateObject("Outlook.Application")
        End If

        If Err <> 0 Then

            If Err = 462 Then                         'Outlook is wrong or not _
                                                        available
                MsgBox _
                    "The correct version of Outlook is not available.  Please contact your company's IT professional to install Outlook 2000 (or later version).", _
                    vbCritical, "Missing Outlook"
                Exit Sub
            Else
                MsgBox _
                    "There is a problem with your e-mail.  Please call Medici support." _
                    & vbCrLf & "The error is No. " & Err.Number & " which is " & _
                    Err.Description, vbCritical, _
                    "Documenter - prjLoanWright.basMails.General.SendMail"
                Exit Sub
            End If

        End If
       
        On Error GoTo EHandler
       
        Set ns = ol.GetNamespace("MAPI")
        sVer = ol.version
        If InStr(1, sVer, ".") <> 0 Then
            sVer = Left(sVer, InStr(1, sVer, ".") - 1)
        End If
       
        If IsNumeric(sVer) Then
            iVer = CInt(sVer)
        Else
            iVer = 0
        End If
       
        If iVer >= 10 Then
            ns.logon , , , False
        End If
       
        Set newmail = Nothing
        'Create a new mail message item
        Set newmail = ol.CreateItem(0)
       
        If (Nothing Is newmail) Then
            GoSub Cleanup
            MsgBox "Cannot create outlook mail item. " + vbCrLf + Err.Description, vbCritical, "Documenter"
            Exit Sub
        End If

        ' Mail created, populate the message with information
        With newmail
            .Subject = "Output File(s) & help documents "
            .Body = vbCrLf & vbCrLf
            .Body = "Test E-Mail Body" & _
                        vbCrLf & "Please note this is only a test"
        End With
       
        ' Show outlook message compose window
        newmail.Display 1

        'force the email to send in Outlook XP or later even if Outlook is not open
        If iVer >= 10 Then
            For i = 1 To ns.SyncObjects.Count
                ns.SyncObjects.Item(i).Start
            Next i
            If intSleepTime > 0 Then
                Sleep intSleepTime
            End If
            ns.Logoff
        End If
        GoSub Cleanup
        Exit Sub
    EHandler:
        MsgBox "Number: " & Err.Number & vbCrLf & "Desc: " & Err.Description & vbCrLf & _
            "Source: " & Err.Source
        GoSub Cleanup
        Exit Sub

    Cleanup:
        Set ol = Nothing
        Set ns = Nothing
        Set newmail = Nothing
        Return

    End Sub

    VB.NET (VS2005) Sample:

    Private Sub SendEmailTest()
            Dim i As Short
            Dim iVer As Short
            Dim sVer As String
            Dim intSleepTime As Short
            Dim ol As Object
            Dim ns As Object
            Dim newmail As Object

            On Error Resume Next
            Err.Clear()

            ol = CreateObject("Outlook.Application")

            If Err.Number <> 0 Then

                If Err.Number = 462 Then 'Outlook is wrong or not available
                    MsgBox("The correct version of Outlook is not available.  Please contact your company's IT professional to install Outlook 2000 (or later version).", MsgBoxStyle.Critical, "Missing Outlook")
                    Exit Sub
                Else
                    MsgBox("There is a problem with your e-mail.  Please call Medici support." & vbCrLf & "The error is No. " & Err.Number & " which is " & Err.Description, MsgBoxStyle.Critical, "Documenter - prjLoanWright.basMails.General.SendMail")
                    Exit Sub
                End If

            End If

            On Error GoTo EHandler

            ns = ol.GetNamespace("MAPI")
            sVer = ol.version
            If InStr(1, sVer, ".") <> 0 Then
                sVer = VB.Left(sVer, InStr(1, sVer, ".") - 1)
            End If

            If IsNumeric(sVer) Then
                iVer = CShort(sVer)
            Else
                iVer = 0
            End If

            If iVer >= 10 Then
                ns.logon(, , , False)
            End If

            newmail = Nothing
            'Create a new mail message item
            newmail = ol.CreateItem(0)

            If (Nothing Is newmail) Then
                ol = Nothing
                ns = Nothing
                newmail = Nothing
                MsgBox("Cannot create outlook mail item. " & vbCrLf & Err.Description, MsgBoxStyle.Critical, "Documenter")
                Exit Sub
            End If

            ' Mail created, populate the message with information
            With newmail
                .Subject = "Output File(s) & help documents "
                .Body = vbCrLf & vbCrLf
                .Body = "Test E-Mail Body" & vbCrLf & "Please note this is only a test"
            End With

            ' Show outlook message compose window
            newmail.Display(1)

            'force the email to send in Outlook XP or later even if Outlook is not open
            If iVer >= 10 Then
                For i = 1 To ns.SyncObjects.Count
                    ns.SyncObjects.Item(i).Start()
                Next i
                If intSleepTime > 0 Then
                    Sleep(intSleepTime)
                End If
                ns.Logoff()
            End If
            ol = Nothing
            ns = Nothing
            newmail = Nothing
            Exit Sub
    EHandler:
            MsgBox("Number: " & Err.Number & vbCrLf & "Desc: " & Err.Description & vbCrLf & "Source: " & Err.Source)
            ol = Nothing
            ns = Nothing
            newmail = Nothing
            Exit Sub
        End Sub

    Tuesday, January 29, 2013 6:20 PM

Answers

  • This is to be expected - Outlook closes itself down after its last window (such as the inspector shown by your call to Display) is closed.

    This was done as a guard agaist applications that forgot to release Outlook objects and forced outlook.exe to stay in memory.

    Do not cache any Outlook objects in global variables - use CreateObject() every time you need an instance of the Outlook.Application object.


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

    • Marked as answer by CBar Tuesday, January 29, 2013 10:49 PM
    Tuesday, January 29, 2013 7:06 PM
  • Yes, it all started in Outlook 2007.

    Outlook does need to have its UI shown to stay in memory - I don't remember if keeping an Inspector (MailItem.GetInspector) or Explorer (MAPIFolder.GetExplorer) object is sufficient.

    Reinstantiate your instance of Outlook every time your code is executed, do not keep any Outlook objects referenced in anything but local variables.


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

    • Marked as answer by CBar Tuesday, January 29, 2013 10:49 PM
    Tuesday, January 29, 2013 7:48 PM

All replies

  • This is to be expected - Outlook closes itself down after its last window (such as the inspector shown by your call to Display) is closed.

    This was done as a guard agaist applications that forgot to release Outlook objects and forced outlook.exe to stay in memory.

    Do not cache any Outlook objects in global variables - use CreateObject() every time you need an instance of the Outlook.Application object.


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

    • Marked as answer by CBar Tuesday, January 29, 2013 10:49 PM
    Tuesday, January 29, 2013 7:06 PM
  • Hi Dmitry--

    Thank you for the information.  I had not come across that anywhere.

    Do you know if this was new functionality beginning with Outlook 2007?  In prior versions of Outlook, this code did not have any trouble.

    It sounds like there is no way around this unless I display some other part of the Outlook App as well?  Either that or I have to re-instantiate my instance of Outlook after I call the Display method?

    Again, many thanks for the information.

    Tuesday, January 29, 2013 7:39 PM
  • Yes, it all started in Outlook 2007.

    Outlook does need to have its UI shown to stay in memory - I don't remember if keeping an Inspector (MailItem.GetInspector) or Explorer (MAPIFolder.GetExplorer) object is sufficient.

    Reinstantiate your instance of Outlook every time your code is executed, do not keep any Outlook objects referenced in anything but local variables.


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

    • Marked as answer by CBar Tuesday, January 29, 2013 10:49 PM
    Tuesday, January 29, 2013 7:48 PM
  • Thanks.  You've given me some avenues to run along testing to see if I can find a resolution.

    Our code does not keep the outlook item around and open.  We instantiate it only when needed, and shut it down when we are done.  The issue is now apparently that Outlook 2007+ is shutting itself down in the middle of our use. 

    Let me see if I can come up with a work around in code.

    Tuesday, January 29, 2013 7:52 PM
  • Do uou mean you need to keep it alive while you work with the SyncObjects collection?

    Tyr ot retrieve the inspector before calling Display, and release only after you are done just before your sub exits.


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

    Tuesday, January 29, 2013 8:12 PM
  • Yes, we do it all in one sub, so we need to have it working throughout the entire sub.

    The Inspector approach did not work.  However, I instantiated an instance of a default folder (inbox, in this case) and then got the Explorer object from that.  Looks like holding on to that keeps Outlook alive even after the "display" call, so that piece of advice looks like it has resolved the problem for me.

    MANY, MANY Thanks!

    Tuesday, January 29, 2013 10:48 PM