VC++中使用IManagedAddin加载VSTO VBA Outlook插件优化启动时间
解决方案
关于IManagedAddin接口的说明
你不需要自己实现IManagedAddin接口,这个接口是微软官方VSTO运行时自带的加载器组件实现的,你写的IManagedAddin.h仅用于声明接口结构,方便你调用加载器的Load方法加载托管VSTO插件,无需自行编写该接口的实现逻辑。
1. 修复(???)处的接口查询问题
调用IManagedAddin::Load后,加载器已经完成了托管VSTO插件的实例化,你获取到的ext指针就是托管插件的_IDTExtensibility2实现,直接用该指针查询IRibbonExtensibility即可:
hr = ext->QueryInterface(MSO::IID_IRibbonExtensibility, (void**)&ribbon);
2. 补全存根插件的Ribbon转发逻辑
Outlook会主动向插件查询Ribbon配置,你需要让C++存根实现IRibbonExtensibility接口,并将所有相关请求转发给已加载的托管插件:
- 修改CConnect的继承列表,新增
public MSO::IRibbonExtensibility - 在COM_MAP中添加对应接口项:
BEGIN_COM_MAP(CConnect) COM_INTERFACE_ENTRY(IConnect) COM_INTERFACE_ENTRY2(IDispatch, _IDTExtensibility2) COM_INTERFACE_ENTRY(_IDTExtensibility2) COM_INTERFACE_ENTRY(MSO::IRibbonExtensibility) // 新增 END_COM_MAP() - 将
ribbon指针设为CConnect的静态成员,然后实现GetCustomUI方法:STDMETHOD(GetCustomUI)(BSTR RibbonID, BSTR * RibbonXml) { if (!ribbon) return S_FALSE; return ribbon->GetCustomUI(RibbonID, RibbonXml); }
3. 补充资源释放逻辑
现有代码存在内存泄漏风险,需要补充以下释放逻辑:
SysAllocString分配的manifestUrl用完后调用SysFreeString(manifestUrl)释放- 所有COM指针(
loader、ext、ribbon等)用完后调用Release()方法释放 - 在存根的
OnDisconnection方法中转发调用托管插件的OnDisconnection方法,避免资源泄漏
4. 注册表配置注意事项
仅保留C++存根插件的COM注册信息,删除原有托管VSTO插件的注册表项,避免Outlook重复加载插件。
该方案的核心逻辑是用启动速度极快的C++原生插件通过Outlook的启动耗时检测(一般仅几十毫秒,远低于1000ms阈值),再通过定时器延后加载托管VSTO插件,延后加载的时间不计入Outlook的插件启动耗时统计,不会触发自动禁用规则。
内容的提问来源于stack exchange,提问作者TF.Ryan
相关产品推荐
相关产品推荐

