AppDomain中的COM RCW引用计数

时间:2013-08-26 07:16:16

标签: c# com outlook office-interop

我有一个Outlook AddIn,我正在加载单独的AppDomain。然后我将Outlook(COM RCW)对象传递到这些AppDomains中。这项工作的基础很好,但是当我从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 - 针对同一项目再次收到两个“未保存的更改”提示,指示未发布的对邮件项目的引用。
  5. 问题似乎在于对mail.PropertyAccessor和后续ReleaseComObject的调用。这个应该释放引用,并且从ReleaseComObject 返回的引用计数为零,但显然仍有引用,因为从{{1中删除了这些行方法导致在步骤4中没有“未保存的更改”提示。对于它的价值,向上移动到更强大的DoWork方法没有任何区别。

    Marshal.FinalReleaseComObject代码也没有任何内在错误。将其移出mail.PropertyAccessor方法,然后进入功能区按钮单击事件处理程序,正如人们所预料的那样,在步骤4中没有未保存的更改提示。

    这里发生了什么?

    编辑1

    它似乎也会在单独的AppDomain中访问访问属性。 DoWork导致问题,但PropertyAccessor没有。 RecipientsSessionApplication也都可以。实际上到目前为止,我发现麻烦的唯一MailItem属性是Attachments

0 个答案:

没有答案