从托管代码调用 Folder.PropertyAccessor 安全吗?

Is Folder.PropertyAccessor safe to call from managed code?

我们最近完成了 VSTO Outlook 加载项的开发。对于某些配置数据,它在 Folder.

上使用自定义 olText 属性

当我们的加载项检测到这些属性不可用时,它会使用文件夹的 UserDefinedProperties 属性 到 Find/Add 我们的自定义属性(如果它们不存在)。

if (folder.UserDefinedProperties.Find(propertyName) == null)
    folder.UserDefinedProperties.Add(propertyName, OlUserPropertyType.olText);

虽然我们的加载项是 运行,但我们多次获取和设置这些属性。我们使用 PropertyAccessor GetProperty 和 SetProperty 方法来做到这一点。同样,我们所有的属性都是 OlUserPropertyType.olText 类型。此外,我们总是在获取和设置属性时分派到 Outlook 的 UI 线程。

//set
string value = "blah";
folder.PropertyAccessor.SetProperty(GetSchemaName(propertyName), value);

// get
string value = folder.PropertyAccessor.GetProperty(GetSchemaName(propertyName)

GetSchemaName returns ("http://schemas.microsoft.com/mapi/string/" + assemblyGuid + "/" + 属性Name).

但是,我们在文件夹的 PropertyAccessor 上使用 GetProperty 和 SetProperty 会导致频繁的运行时 COMExceptions。下面是调用 GetProperty 的异常示例。我们在 Outlook 2010 和 2013 中都看到了这个问题。

System.Runtime.InteropServices.COMException (0x80020005): Type mismatch.
(Exception from HRESULT: 0x80020005 (DISP_E_TYPEMISMATCH))
at Microsoft.Office.Interop.Outlook._PropertyAccessor.GetProperty(String SchemaName)

我的问题是:使用 Folder PropertyAccessor 在 VSTO 中获取和设置属性是否存在已知问题?如果不是,为什么会这样?

不,这不是已知问题。

GetSchemaName(propertyName)

传递给 Get/SetProperty 方法的实际值是多少?

无论如何,我建议改用 StorageItem class。以下是 MSDN 的说明:

GetStorage 方法使用 StorageIdentifier 指定的标识符获取 Folder 对象上的 StorageItem,并具有 StorageIdentifierType 指定的标识符类型。 StorageItem是Folder中的隐藏项,随账号漫游,在线离线均可使用。

如果您使用 StorageIdentifierType 的 olIdentifyByEntryID 值指定 StorageItem 的 EntryID,则 GetStorage 方法将 return 具有指定 EntryID 的 StorageItem。如果使用该 EntryID 找不到 StorageItem 或者 StorageItem 不存在,则 GetStorage 方法将引发错误。

如果您使用 StorageIdentifierType 的 olIdentifyByMessageClass 值为 StorageItem 指定消息 class,则 GetStorage 方法将 return 具有指定消息 [=42] 的 StorageItem =].如果有多个项目具有相同的消息 class,则 GetStorage 方法 return 将具有最近的 PR_LAST_MODIFICATION_TIME 的项目。如果不存在具有指定消息 class 的 StorageItem,则 GetStorage 方法会创建一个新的 StorageItem,其消息 class 由 StorageIdentifier 指定。

如果您指定 StorageItem 的主题,则 GetStorage 方法将 return 具有在 GetStorage 调用中指定的主题的 StorageItem。如果有多个项目具有相同的主题,则 GetStorage 方法将 return 具有最新 PR_LAST_MODIFICATION_TIME 的项目。如果不存在具有指定主题的 StorageItem,则 GetStorage 方法将使用 StorageIdentifier 指定的主题创建一个新的 StorageItem。

使用文件夹 class 的 GetStorage 方法获取父文件夹上的 StorageItem 对象以存储 Outlook 解决方案的数据。

有关详细信息,请参阅 Storing Data for Solutions

您最终在文件夹上设置了命名的 MAPI 属性。请记住,虽然 PST 提供商支持,但 Exchange 提供商不支持。您需要重新考虑将属性存储在文件夹本身上的需要,或者在文件夹中的隐藏(关联)邮件上设置此类属性。这就是 MAPIFolder.GetStorage uses and that is how Outlook stores its own per-folder settings (such as views). Take a look at the existing data (Inbox is a good candidate) in OutlookSpy(我是它的作者)- 单击 IMAPIFolder,转到“相关内容”选项卡。