C# Outlook互操作。尝试几次后,oSelection开始返回旧的选择项

C# Outlook互操作。尝试几次后,oSelection开始返回旧的选择项,c#,.net,email,outlook,ms-office,C#,.net,Email,Outlook,Ms Office,我有这样的代码,在这里我可以访问outlook资源管理器来获取所选项目。我第一次访问它时,它会返回一封电子邮件,现在如果我转到outlook并选择较旧的电子邮件,它会返回两封电子邮件,而不是仅返回一封。如果我更进一步,选择新的项目,而不是多选,只是简单的单选,它们开始堆积起来 代码如下: public IEnumerable<MailItemVM> GetSelectedMailItem() { RetrieveOutlookProcessHa

我有这样的代码,在这里我可以访问outlook资源管理器来获取所选项目。我第一次访问它时,它会返回一封电子邮件,现在如果我转到outlook并选择较旧的电子邮件,它会返回两封电子邮件,而不是仅返回一封。如果我更进一步,选择新的项目,而不是多选,只是简单的单选,它们开始堆积起来

代码如下:

public IEnumerable<MailItemVM> GetSelectedMailItem()
        {
            RetrieveOutlookProcessHandle(false);

            List<MailItemVM> result = new List<MailItemVM>();

            //olApp = new Microsoft.Office.Interop.Outlook.Application();
            //KillOlProcess = true;

            Microsoft.Office.Interop.Outlook.Explorer oExplorer = olApp.ActiveExplorer();
            Microsoft.Office.Interop.Outlook.Selection oSelection = oExplorer.Selection;

            foreach (object item in oSelection)
            {
                Microsoft.Office.Interop.Outlook.MailItem mi = (Microsoft.Office.Interop.Outlook.MailItem)item;

                if (mi != null)
                {
                    MailItemVM mVM = new MailItemVM()
                    {
                        Title = mi.Subject,
                        Description = mi.BodyFormat == Microsoft.Office.Interop.Outlook.OlBodyFormat.olFormatHTML ? mi.HTMLBody : mi.Body
                    };
                    result.Add(mVM);
                }
                break;

            }

            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(olApp);
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oExplorer);
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(oSelection);
            System.Runtime.InteropServices.Marshal.FinalReleaseComObject(olNS);

            var olProcess = Process.GetProcessesByName("OUTLOOK").FirstOrDefault();

            olApp = null;
            olNS = null;

            if (KillOlProcess && olProcess != null)
            {
                olProcess.Kill();
            }

            return result;
        }

private void RetrieveOutlookProcessHandle(bool forceNewApp)
        {
            // Check whether there is an Outlook process running.
            if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
            {
                // If so, use the GetActiveObject method to obtain the process and cast it to an Application object.
                olApp = Marshal.GetActiveObject("Outlook.Application") as Microsoft.Office.Interop.Outlook.Application;
                KillOlProcess = false;
            }
            else if (!forceNewApp)
            {
                // If not, create a new instance of Outlook and log on to the default profile.
                olApp = new Microsoft.Office.Interop.Outlook.Application();
                KillOlProcess = true;
            }
            else
                throw new InvalidOperationException("Outlook must be running or invalid state");

            olNS = olApp.GetNamespace("MAPI");
        }

这听起来很像这个问题:

Outlook、自定义任务窗格和拖放问题:C、VB.NET

由于您没有进行自定义拖放,我认为罪魁祸首可能是对MailItem对象的未发布引用。我会从foreach中重构并使用for count,因为foreach调用在Outlook中迭代集合时是个坏消息


但最重要的是:在完成每个项目后调用ReleaseComObject。

foreach是一个非常好的想法,我的朋友,oSelection变量应该是动态的,并通过它作为集合访问。此外,我还做了自定义拖放。然而,我是在WPF中而不是在winforms中进行的,并找到了一个更快的解决方案。。。在每次拖放时释放com对象,无需自定义拖放目标。MS中的人可能在dragover事件中解决了这个问题,获得了IDataObject参考。非常感谢你为我指明了正确的方向!