实现对象创建扩展 COM 对象

对象创建扩展是作为进程内服务器实现的 COM 对象。 主对象创建扩展和辅助对象创建扩展都必须实现 IDsAdminNewObjExt 接口。

实现 IDsAdminNewObjExt

创建对象创建向导时,它通过调用扩展的 IDsAdminNewObjExt::Initialize 来初始化每个对象创建扩展。 Initialize 为扩展提供有关创建对象的容器的信息、新对象的类名以及有关向导本身的信息。 如果启动对象创建向导以从现有对象创建新对象,则 pADsCopySource 参数将不会为 NULL。 在这种情况下,扩展会尝试从复制的对象获取尽可能多的数据。

初始化扩展后,将调用 IDsAdminNewObjExt::AddPages 方法。 在此方法期间,扩展必须向向导添加一个或多个页面。 通过填充 PROPSHEETPAGE 结构,然后将该结构传递给 CreatePropertySheetPage 函数,可以创建向导页。 然后,通过调用在 lpfnAddPage 参数中传递给 AddPages 的回调函数,将该页添加到向导中。

在显示扩展页之前,调用 IDsAdminNewObjExt::SetObject。 这为扩展提供了一个 IADs 接口指针,用于正在创建的对象。

显示向导页面时,该页面应处理并响应任何必要的向导通知消息,如 PSN_SETACTIVEPSN_WIZNEXT

当用户完成所有向导页时,向导将显示一个“完成”页,该页提供输入的数据摘要。 向导通过为每个扩展调用 IDsAdminNewObjExt::GetSummaryInfo 方法来获取此数据。 GetSummaryInfo 方法提供一个 BSTR,其中包含“完成”页中显示的文本数据。 对象创建扩展不需要提供摘要数据。 在这种情况下,GetSummaryInfo 应返回 E_NOTIMPLGetSummaryInfo 仅为每个扩展调用一次,而不是每页调用一次。因此,如果对象创建扩展添加了多个页面,则扩展必须将摘要数据合并到一个字符串中。

当用户单击“完成”页面中的完成按钮时,向导将使用 DSA_NEWOBJ_CTX_PRECOMMIT 上下文调用每个扩展的 IDsAdminNewObjExt::WriteData 方法。 发生这种情况时,扩展应使用 IADs::PutIADs::PutEx 方法将收集的数据写入适当的属性。 IADs 接口通过 IDsAdminNewObjExt::SetObject 方法提供给扩展。 扩展不应通过调用 IADs::SetInfo 提交缓存的属性。 写入所有属性后,主对象创建扩展将通过调用 IADs::SetInfo 来提交更改。 下面对此有详细讨论。

如果发生错误,当调用 IDsAdminNewObjExt::OnError 方法时,扩展将被通知该错误以及发生在哪个操作期间。

实现主对象创建向导

主对象创建向导的实现与辅助对象创建向导相同,只是主对象创建向导必须执行几个其他步骤。

在关闭第一个页面之前,对象创建向导必须创建临时目录对象。 要执行此操作,请调用 IDsAdminNewObjPrimarySite::CreateNew 方法。 在传递给 IDsAdminNewObjExt::InitializeIDsAdminNewObj 接口上,用 IID_IDsAdminNewObjPrimarySite 调用 QueryInterface,可以获得指向 IDsAdminNewObjPrimarySite 接口的指针。 CreateNew 方法创建一个新的临时对象,并为每个扩展调用 IDsAdminNewObjExt::SetObject

当对象创建向导包含多个页面时,系统将实现一个“完成”页,其中显示要保存的对象信息的摘要。 单击“完成”页上的完成按钮时,系统将调用每个对象创建扩展的 IDsAdminNewObjExt::WriteData 方法,然后将临时对象提交到永久性内存。 但是,如果对象创建向导仅包含一页,则页面将具有确定取消按钮,而不是向导中常见的后退下一步取消按钮,并且不提供“完成”页面。 因此,单页对象创建扩展向导必须调用 IDsAdminNewObjPrimarySite::Commit 来执行写入和保存操作。 单页主对象创建扩展应调用 Commit 以响应 PSN_WIZFINISH 通知。

由于其他对象创建扩展插件可以将页面添加到向导中,因此主对象创建扩展可能不知道向导中是否有多个页面。 这不是一个问题,有两个原因:首先,如果系统实现“完成”页,主对象创建扩展将收到 PSN_WIZNEXT 通知,而不是 PSN_WIZNEXT 通知。 其次,如果向导包含多个页面,则 Commit 将失败,不会造成危害。