2

The following problem is driving me crazy. In C#, I am trying to ensure that outlook shuts down after I run some code to grab all calendar events, yet no matter what I try, it doesn't. Can anyone help me?

private void button1_Click(object sender, EventArgs e)
{
    Microsoft.Office.Interop.Outlook.Application outlookApp = null;
    Microsoft.Office.Interop.Outlook.NameSpace mapiNamespace = null;
    Microsoft.Office.Interop.Outlook.MAPIFolder CalendarFolder = null;
    Microsoft.Office.Interop.Outlook.Items outlookCalendarItems = null;

    outlookApp = new Microsoft.Office.Interop.Outlook.Application();
    mapiNamespace = outlookApp.GetNamespace("MAPI");

    CalendarFolder = mapiNamespace.GetDefaultFolder(Microsoft.Office.Interop.Outlook.OlDefaultFolders.olFolderCalendar);
    outlookCalendarItems = CalendarFolder.Items;

    outlookCalendarItems.IncludeRecurrences = true;
    foreach (Microsoft.Office.Interop.Outlook.AppointmentItem item in outlookCalendarItems)
    {
        if (item.IsRecurring)
        {
            Microsoft.Office.Interop.Outlook.RecurrencePattern rp = item.GetRecurrencePattern();
            DateTime first = new DateTime(2008, 8, 31, item.Start.Hour, item.Start.Minute, 0);
            DateTime last = new DateTime(2008, 10, 1);
            Microsoft.Office.Interop.Outlook.AppointmentItem recur = null;

            for (DateTime cur = first; cur <= last; cur = cur.AddDays(1))
            {
                try
                {
                    recur = rp.GetOccurrence(cur);
                    MessageBox.Show(recur.Subject + " -> " + cur.ToLongDateString());
                }
                catch
                {
                }
            }
        }
        else
        {
            MessageBox.Show(item.Subject + " -> " + item.Start.ToLongDateString());
            break;
        }
    }

    ((Microsoft.Office.Interop.Outlook._Application)outlookApp).Quit();
    //outlookApp.Quit();
    //(outlookApp as Microsoft.Office.Interop.Outlook._Application).Quit();

    outlookApp = null;

    System.Runtime.InteropServices.Marshal.ReleaseComObject(outlookCalendarItems);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(CalendarFolder);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(mapiNamespace);
    //System.Runtime.InteropServices.Marshal.ReleaseComObject(outlookApp);

    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(outlookCalendarItems);
    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(CalendarFolder);

    System.Runtime.InteropServices.Marshal.FinalReleaseComObject(mapiNamespace);
    //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(outlookApp);
    GC.Collect();
    GC.WaitForPendingFinalizers();

    mapiNamespace = null;
    CalendarFolder = null;
    outlookCalendarItems = null;
}
Xaruth
  • 4,034
  • 3
  • 19
  • 26
scadav
  • 33
  • 1
  • 4

3 Answers3

0

Have you debugged your code to see if the application ever gets to the OutlookApp.Quit() command?

The only other way around this would be to crudley kill the process "Outlook.exe".

Derek
  • 8,300
  • 12
  • 56
  • 88
  • Yes. I debugged and it made it all the way to the end. I thought about crudley killing it, but wasn't sure how to tell if the process I was killing was a 'real' version of outlook someone has up or the version that my program launched. – scadav Apr 12 '12 at 17:49
  • When you launch it grab the PID. Then you can kill the process by PID. – Jimmy D Apr 12 '12 at 19:11
0

Temporary hardcore solution:

public static class OutlookKiller
{
        [DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
CharSet = CharSet.Unicode, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
    private static extern long GetWindowThreadProcessId(long hWnd, out long lpdwProcessId);

    public static void Kill(ref Microsoft.Office.Interop.Outlook.Application app)
    {
        long processId = 0;
        long appHwnd = (long)app.Hwnd;

        GetWindowThreadProcessId(appHwnd, out processId);

        Process prc = Process.GetProcessById((int)processId);
        prc.Kill();
    }
}
cookieMonster
  • 508
  • 6
  • 15
0

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...

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);
            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)
    {
        //Process[] remoteByName = Process.GetProcessesByName("notepad", "myComputer");
        // 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 call it at the beginning and end of my app with the following one Killer line of code:

    KillProcessByPID.KillProcessByName("OUTLOOK");

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.

Danimal111
  • 1,976
  • 25
  • 31