Reputation: 361
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
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
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;
}
}
Upvotes: 4