我有一个 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;
}
使用场景很简单:
- 单击“新电子邮件”。
- 单击功能区中的加载项按钮。
- 关闭电子邮件 - 在未保存的更改提示上选择“否”。
- 关闭 Outlook - 针对同一项目收到另外两个“未保存的更改”提示,表示对邮件项目的未发布引用。
问题似乎在于对mail.PropertyAccessor
和后续的调用ReleaseComObject
。这应该是释放引用,并且从返回的引用计数ReleaseComObject
为零,但显然仍然存在引用,因为从DoWork
方法中删除这些行会导致步骤 4 中没有“未保存的更改”提示。对于它的价值,移动到更多的蛮力Marshal.FinalReleaseComObject
方法没有区别。
代码本质上也没有任何问题mail.PropertyAccessor
。将其移出DoWork
方法并向上移动到功能区按钮单击事件处理程序中,正如预期的那样,在第 4 步没有未保存的更改提示。
这里发生了什么?
编辑 1
在单独的 AppDomain 中访问什么属性似乎也有所不同。PropertyAccessor
导致问题,但Recipients
不会。Session
,Application
也Attachments
都OK。事实上,到目前为止,我发现唯一有问题的 MailItem 属性是PropertyAccessor
.