1

我有一个 Outlook 插件,我正在将单独的 AppDomain 加载到其中。然后,我将 Outlook (COM RCW) 对象传递到这些 AppDomain 中。这项工作的基础很好,但是当我从 AppDomain 中获取另一个对象引用时,引用计数似乎变得不稳定。

举个简单的例子,我在 Mail.Compose 功能区上有一个按钮,带有一个点击处理程序。此代码在主要 Outlook 加载项 AppDomain 中执行。

var execAsm = System.Reflection.Assembly.GetExecutingAssembly();
var loadUri = new Uri(execAsm.CodeBase);
string loadDir = System.IO.Path.GetDirectoryName(loadUri.LocalPath);

// Create app-domain
AppDomainSetup appSetup = new AppDomainSetup();
appSetup.ApplicationBase = loadDir;
System.Security.PermissionSet permSet = 
   new System.Security.PermissionSet(
   System.Security.Permissions.PermissionState.Unrestricted);
var myDomain = AppDomain.CreateDomain("MyDomain", null, appSetup, permSet, null);

// Get instance from app-domain
dynamic addInPoint = myDomain.CreateInstanceAndUnwrap(
    assemblyName: "ClassLibrary1",
    typeName: "ClassLibrary1.Class1");

// Do work on mail item
Outlook.MailItem currentMail = 
    Outlook.MailItem)Globals.ThisAddIn.Application.ActiveInspector()
    .CurrentItem;
addInPoint.DoWork(currentMail);

// Clean-up
Marshal.ReleaseComObject(currentMail);
currentMail = null;

以及下面的Class实现。需要明确的是,这只会在单独的 AppDomain 中执行。

public void DoWork(Outlook.MailItem mail)
{
    mail.Save();
    mail.To = "foobar@test.com";

    var propAccessor = mail.PropertyAccessor;
    Marshal.ReleaseComObject(propAccessor);
    propAccessor = null;
}

使用场景很简单:

  1. 单击“新电子邮件”。
  2. 单击功能区中的加载项按钮。
  3. 关闭电子邮件 - 在未保存的更改提示上选择“否”。
  4. 关闭 Outlook - 针对同一项目收到另外两个“未保存的更改”提示,表示对邮件项目的未发布引用。

问题似乎在于对mail.PropertyAccessor和后续的调用ReleaseComObject。这应该是释放引用,并且从返回的引用计数ReleaseComObject 为零,但显然仍然存在引用,因为从DoWork方法中删除这些行会导致步骤 4 中没有“未保存的更改”提示。对于它的价值,移动到更多的蛮力Marshal.FinalReleaseComObject方法没有区别。

代码本质上也没有任何问题mail.PropertyAccessor。将其移出DoWork方法并向上移动到功能区按钮单击事件处理程序中,正如预期的那样,在第 4 步没有未保存的更改提示。

这里发生了什么?

编辑 1

在单独的 AppDomain 中访问什么属性似乎也有所不同。PropertyAccessor导致问题,但Recipients不会。SessionApplicationAttachments都OK。事实上,到目前为止,我发现唯一有问题的 MailItem 属性是PropertyAccessor.

4

0 回答 0