Search code examples
c#outlookoffice-interop

Microsoft Outlook is not closing after automation is finished (C++ -> C# -> Outlook) via COM


This is my Visual C++ wrapper that initialises own DLL library:

void COutlookManagerEx::Init()
{
    throw_if_fail(m_pInterface.CreateInstance(__uuidof(PTSOutlookLibrary::PTSOutlookLibraryClass)));
    if (IsValid())
        m_pInterface->ShowMicrosoftOutlook();
}

The C# constructor:

public PTSOutlookLibraryClass()
{
    try
    {
        _OutlookApp = new Outlook.Application();
    }
    catch(Exception /* e */)
    {

    }
}

The C# method to display Outlook:

public void ShowMicrosoftOutlook()
{
    // Show Outlook
    if (_OutlookApp.Explorers.Count == 0)
    {
        Outlook.MAPIFolder oFolder = _OutlookApp.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);
        oFolder.Display();
    }
}

My COutlookManagerEx is a member variable of a CDialog:

private:
    COutlookManagerEx m_OutlookManager;

For some reason, when I close my CDialog object Microsoft Outlook stays open.

Update

Based on similar questions I have tried:

   public void Terminate()
    {
        try
        {
            Marshal.ReleaseComObject(_OutlookApp);
        }
        catch
        {

        }
        finally
        {
            _OutlookApp = null;
        }
    }

And adding my own wrapper and then calling Terminate when my dialog closes but Outlook is still visible.


Solution

  • Are you running any VBA macros in Outlook when you instantiate it? Is VBA an option for you? I do automation in Excel in the background, and I've found that I get the most reliable results when I instantiate the program using VB Script and then execute VBA either from inside Excel or through the VB Script interface. That way, I can run the VBS script in the background, and I can leverage VBA commands like DisplayAlerts and Quit to hide things or exit the software. I can also get around user access issues by leveraging a credentials store and executing the VBS as a user with required permissions to access the files (as VBS will start the COM object with the credentials provided at it's own execution time.)

    But whatever wrapper you choose to use, you should be sending a quit command to outlook before you close the COM object. I've found that if I don't quit Excel first, and then close the COM object, there's a chance that the software just stays open, especially if it's expecting user input of some kind (IE: "Are you sure you want to quit?"). And of course, on the other end of the spectrum, if you call 'Quit' but don't kill your COM object, you'll have a hanging process.

    The order of operations to quit should be from the bottom up. Quit Outlook, then kill the COM object, then end your program.


    All that being said:

    Automation of Outlook, Excel, and all other office suite programs is unsupported. Unless you're automating some kind of legacy script, or working with people uncomfortable (or unfamiliar) with writing software, you should probably be leveraging the fact that Microsoft Office now follows the open office suite standard:

    https://support.microsoft.com/en-us/help/257757/considerations-for-server-side-automation-of-office

    You're comfortable with C#, and all office documents are XML files. If you're sending or receiving E-Mails, you could probably use SMTP clients built into C#, or implement something that gets done what you need. If you're building something new, I'd strongly recommend staying away from Office Automation.