outlook email
outlook email

Reputation: 361

How to close outlook after automating it in c#

I am creating a program which converts Msg outlook file into pdf. What I did was export the Msg file into Html then convert the Html output to pdf. This is my code:

Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();

string filename = System.IO.Path.GetFileNameWithoutExtension(msgLocation) + ".html";
string attachmentFiles = System.IO.Path.Combine(System.IO.Path.GetTempPath(), System.IO.Path.GetFileNameWithoutExtension(msgLocation) + "_files");
string extractLocation = System.IO.Path.Combine(System.IO.Path.GetTempPath(), filename);

Console.WriteLine(filename);
Console.WriteLine(attachmentFiles);
Console.WriteLine(extractLocation);
var item = app.Session.OpenSharedItem(msgLocation) as Microsoft.Office.Interop.Outlook.MailItem;
item.SaveAs(extractLocation, Microsoft.Office.Interop.Outlook.OlSaveAsType.olHTML);

int att = item.Attachments.Count;
if (att > 0)
{
    for (int i = 1; i <= att; i++)
    {
        item.Attachments[i].SaveAsFile(System.IO.Path.Combine(attachmentFiles, item.Attachments[i].FileName));
    }
}

app.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

The MSG file convertion to HTML is working perfectly, but why is outlook.exe is still running? I want to close it, but app.Quit() doesn't close the app.

Upvotes: 4

Views: 4615

Answers (2)

Danimal111
Danimal111

Reputation: 2062

This should work for any and App by referencing the App Name and it will kill all instances of the application. For instance if you have 5 instances of Notepad, it will kill them all...

To Kill the app, use the following:

 KillProcessByPID.KillProcessByName("OUTLOOK");

Create the following static class (c# .net Core 6.0 is my weapon of choice in this case, but it should be fairly universal).

using System.Management;
using System.Diagnostics;


public static class KillProcessByPID
{
    public static void KillProcessByName(string ProcessName)
    {
        string OutlookProcessName = "";
        foreach (Process otlk in Process.GetProcesses())
        {
            if (otlk.ProcessName.ToLower().Contains(ProcessName.ToLower())) //OUTLOOK is the one I am seeking - yours may vary
            {
                OutlookProcessName = otlk.ProcessName;
            }
        }
        //Get process ID by Name
        var processes = Process.GetProcessesByName(OutlookProcessName);
        foreach (var process in processes)
        {
            Console.WriteLine("PID={0}", process.Id);
            Console.WriteLine("Process Handle={0}", process.Handle);
            PortfolioTrackerXML.KillProcessByPID.KillProcessAndChildren(process.Id);
        }
    }


    /// <summary>
    /// Kill a process, and all of its children, grandchildren, etc.
    /// </summary>
    /// <param name="pid">Process ID.</param>
    public static void KillProcessAndChildren(int pid)
    {
        // Cannot close 'system idle process'.
        if (pid == 0)
        {
            return;
        }
        ManagementObjectSearcher searcher = new ManagementObjectSearcher
                ("Select * From Win32_Process Where ParentProcessID=" + pid);
        ManagementObjectCollection moc = searcher.Get();
        foreach (ManagementObject mo in moc)
        {
            KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
        }
        try
        {
            Process proc = Process.GetProcessById(pid);
            proc.Kill();
        }
        catch (ArgumentException)
        {
            // Process already exited.
        }
    }
}

I borrowed from many and I'm not sure where, but I thank you all and give you all credit... apologies for not referencing you directly, but this was instrumental.

Upvotes: -1

Rocklan
Rocklan

Reputation: 8130

The issue is that the outlook com object is holding on to references and stopping the app from closing. Use the following function and pass your "app" object to it:

private void ReleaseObj(object obj)
{
    try 
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
    }
    finally 
    {
        obj = null;
    }
}

See https://blogs.msdn.microsoft.com/deva/2010/01/07/best-practices-how-to-quit-outlook-application-after-automation-from-visual-studio-net-client/

Upvotes: 4

Related Questions