创建公文包协调器
公文包协调器为公文包提供了协调文档不同版本的方法。
关于公文包协调器
公文包协调器合并文档的不同输入版本,以生成文档的单个新输出版本。 可能需要创建公文包协调器来支持文档类型。 本概述介绍公文包协调器并说明如何创建它们。
本文讨论了以下主题:
和解
文档是可复制和更改的信息集合。 如果至少两个文档副本的内容不同,则文档具有不同的版本。 对帐从两个或更多初始版本生成文档的单个版本。 通常,协调的版本是初始版本中的信息与保留最新或最有用的信息的组合。
当公文包确定同一文档的两个或更多个副本不同时,由公文包启动对帐。 在此上下文中充当发起程序的公文包查找并启动与给定文档类型关联的公文包协调器。 协调器比较文档并确定要保留的文档部分。 某些协调程序可能需要用户交互才能完成对帐。 其他可能无需用户交互即可完成对帐。 协调器可以包含在应用程序中,也可以是作为 DLL 实现的扩展。
某些公文包协调器可能会产生残留物。 残留是一个文档,通常具有与初始文档相同的文件类型,其中包含未保存在合并版本中的信息。 残渣通常用于使作者能够快速确定原始文档中未包含在最终合并版本中的信息。 如果协调器支持残留,则会为每个文档的原始版本创建一个残留。 除非发起程序请求它们,否则不会创建残留。
某些公文包协调器与公文包配合使用,以允许用户终止对帐。 对于可能决定不应继续对帐的用户来说,这是一项重要功能。 当对帐需要用户交互并且可能很长时,协调器通常会提供终止对象。 在某些环境中,协调器可能允许部分对帐,使用户能够暂时暂停对帐并在以后恢复。 但是,公文包目前不支持部分对帐。
创建公文包协调器
通过实现对帐接口来创建公文包协调程序。 协调器至少实现 IReconcilableObject 接口和 IPersistStorage 或 IPersistFile 接口。 作为发起方,公文包确定何时需要对帐,并调用 IReconcilableObject::Reconcile 方法来启动对帐。
尽管 IReconcilableObject::Reconcile 提供了一组广泛的对帐功能,但公文包协调程序在大多数情况下只执行最少的对帐。 特别是,公文包不需要协调器来支持残留生成或支持终止对象。 此外,协调器执行单个自上而下对帐,不得返回REC_E_NOTCOMPLETE值:也就是说,它不应尝试部分对帐。
公文包提供 IReconcileInitiator 接口。 公文包协调程序可以使用 IReconcileInitiator::SetAbortCallback 方法设置终止对象。 公文包不使用版本标识符,因此,如果协调器使用 IReconcileInitiator 中的相应方法请求它们,则无法提供文档的早期版本。
公文包传递给表示要协调的文档版本的 IReconcilableObject::协调 文件名字对象。 公文包协调器通过使用 IMoniker::BindToObject 或 IMoniker::BindToStorage 方法获取对版本的访问权限。 后者通常速度更快,建议使用。 协调器必须释放它绑定到的任何对象或存储。
当公文包协调器使用 IMoniker::BindToStorage 时,它会绑定到平面存储 (流) 或 OLE 定义的结构化存储。 如果协调器需要平面存储,则应使用 IMoniker::BindToStorage 请求 IStream 接口。 如果协调器需要结构化存储,则应请求 IStorage 接口。 在这两种情况下,它都应请求只读直接 (非事务) 访问存储;读/写访问权限可能不可用。
最小公文包协调器通常直接查看其他版本的存储,并以非常原始的方式处理嵌入的对象,例如通过在输出版本中包括这两个版本来合并对象的两个版本。
发起程序通过使用 GetClassFile 函数实现的逻辑子集来确定给定文件类型,然后在注册表中查找与给定文件类型关联的协调器类,从而找到相应的公文包协调程序。 与其他 Shell 组件一样,公文包仅通过文件扩展名确定文件类型。 文件的扩展名必须具有为 Briefcase 注册的文件类型,才能调用文件的协调器。 安装协调程序时,必须设置以下窗体的注册表项。
CLSID
{the file CLSID}
Roles
Reconciler
(Default) = {the reconciler-classid}
类必须是快速加载的,必须_MULTIPLEUSE指定,并且除非为对帐接口提供了封送处理器,否则必须是包含在 DLL) 中的进程内服务器 (,而不是 (.exe文件中) 实现的本地服务器。
对帐中的用户交互
公文包协调器应尝试在没有用户交互的情况下执行对帐。 对帐自动化程度越高,用户对流程的感知就越好。
在某些情况下,用户干预可能很有价值。 例如,文档系统可能要求用户在接受文档的合并版本之前查看更改,或者可能需要用户提供说明所做更改的注释。 在这些情况下,发起程序(而不是公文包协调器)负责查询用户和执行用户的指令。
在其他情况下,用户干预可能是必需的,例如,当两个版本以不兼容的方式编辑时。 在这种情况下,发起方或公文包协调程序必须查询用户以了解如何解决冲突的说明。 通常,任何发起程序都不能依赖于完成对帐,而无需期待某些用户交互。 另一方面,协调器可以选择与用户交互来解决冲突或要求发起方执行此操作。
协调嵌入对象
协调文档时,如果公文包协调器发现无法协调的嵌入对象,则公文包协调器本身可能会成为发起程序。 在这种情况下,协调器需要以递归方式协调每个嵌入的对象,并承担发起程序的所有责任。
若要执行递归,公文包协调器将加载 对象并查询相应的接口。 对象的处理程序必须支持 接口。 如果接口的任何方法返回OLE_E_NOTRUNNING值,则协调器必须运行 对象才能执行操作。 由于嵌入对象的代码并非始终可用,因此协调器必须为此条件提供解决方案。 例如,协调器可以在协调的版本中包括嵌入对象的旧版本和新版本。 协调程序不得尝试跨链接进行协调。
发起程序存储正在合并的文档版本。 在许多情况下,发起程序可以访问每个版本的存储,并使用类似的存储保存对帐结果。 但是,有时发起程序可能有一个内存中对象,该对象没有可用的持久版本。 如果包含打开的嵌入对象的文档在保存之前必须进行协调,则可能会出现这种情况。 在这种情况下,发起程序会将对帐结果保存在内存中找到的版本中。
发起程序使用 IPersistStorage 接口将 (加载绑定) 合并版本。 如果已创建初始版本并将 IPersistStorage:: InitNew 方法用于初始版本,则发起程序使用 IPersistStorage:: Load 方法。 加载合并版本时,发起程序使用 QueryInterface 检索 IReconcilableObject 接口的地址。 此接口使发起程序能够访问现有残留物的存储,并提供了一种为任何新残留物创建存储的方法。 然后,发起程序指示接口执行对帐。 发起程序实际上在 IPersistStorage 之前查询 IPersistFile 接口。 如果协调器支持 IPersistFile,则发起程序通过 IPersistFile 而不是 IPersistStorage 方法操作副本 (replica) 。 这允许对未存储为复合文档的文件进行核对。
完成对帐后,发起程序可以使用 IPersistStorage 或 IPersistFile 接口保存合并的版本。 在对帐期间,公文包协调器会根据需要创建残留物,并将其永久性位写入存储。 如果合并的版本是流,则传递给 IPersistStorage::Load 的 IStorage 接口包含名为“Contents”的流,其存储状态设置为STATEBITS_FLAT。 (可以使用 IStorage::Stat 方法设置状态位。) 合并后,发起程序通过以适当的方式写入数据来保存合并的版本。 它应确保将STATEBITS_FLAT设置为适合存储。
残留
发起程序通过在调用 IReconcilableObject::Reconcile 方法时将 pstgNewResidues 参数设置为有效地址来指示是否需要残渣。 如果协调器不支持创建残渣,则必须立即返回REC_E_NORESIDUES值,除非 dwFlags 参数指定 RECONCILEF_NORESIDUESOK 值。
公文包协调器通过创建新的存储元素并将其复制到 pstgNewResidues 指向的数组,将残渣返回给发起程序。 对于结构化存储残渣,协调器复制 IStorage 接口,对于平面存储残渣,它会复制 IStream 或 IStorage 接口,并设置STATEBITS_FLAT标志。 协调器使用 IStorage 创建必要的存储,使用 IStorage::CreateStream 为作为流的残渣创建平面存储,使用 IStorage::CreateStorage 创建结构化存储。
发起程序准备 pstgNewResidues ,以便它不包含 IStorage 命名空间的非保留部分的元素。 公文包协调器将每个残渣放在元素中,该元素的名称与其初始版本的顺序相对应。 例如,第一个残留物包含在“1”中,第二个残渣包含在“2”中,依此类比。 如果协调的对象本身生成残渣,则会在名为“0”的元素中找到它。
公文包协调器单独提交每个新创建的元素,确保发起方有权访问信息。 但是,协调器不会提交 pstgNewResidues 本身。 发起方负责提交此内容或以其他方式释放它。
公文包协调器参考
本部分包含有关对帐接口的信息。 处理错误时,方法只能返回显式定义为可能返回值的那些错误值。 此外, 方法必须将地址作为参数传递的所有变量设置为 NULL ,然后才能从错误返回。
公文包协调器接口和方法