【发布时间】:2021-11-24 17:48:55
【问题描述】:
我收到了一个用 VBA 编写的 VSTO Outlook 加载项,我的任务是减少启动时间。我对整个外接程序和 COM 对象还很陌生,所以我需要一些帮助。
加载项需要 0.2 秒到 2.0 秒才能启动,如果平均启动时间大于 1000 毫秒,Outlook 会禁用该插件。不幸的是,使用注册表破解来强制启用加载项不是一种选择。我还用一个空插件对其进行了测试,它也可能需要 1.8 秒才能启动。我已经搜索了 SO 和其他此类站点以寻找解决方案,并且在一个涉及使用非托管语言(例如 Delphi 或 C++)编写“存根”的解决方案中,除了加载实际加载项之外什么都不做。应该这样做的接口是IManagedAddin。
我的问题是实现这个接口。我在 VC++ 中创建了一个简单的插件实现_IDTExtensibility2 的类在Connect.h 中,如下所示。但是,我不知道如何实现 IManagedAddin::Load 以将我的加载项加载到 Outlook 中,而且似乎没有很多关于此的文档。任何帮助将不胜感激!
编辑:更新以下代码
// Connect.h : Declaration of the CConnect
#pragma once
#include "resource.h" // main symbols
#include "NativeAddin_i.h"
#include "IManagedAddin.h"
#include <Windows.h>
#include <iostream>
#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif
using namespace ATL;
// CConnect
class ATL_NO_VTABLE CConnect :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CConnect, &CLSID_Connect>,
public IDispatchImpl<IConnect, &IID_IConnect, &LIBID_PixelLLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
public IDispatchImpl<_IDTExtensibility2, &__uuidof(_IDTExtensibility2), &LIBID_AddInDesignerObjects, /* wMajor = */ 1, /* wMinor = */ 0>
{
public:
static Outlook::_Application* outlookApp;
static ext_ConnectMode connectMode;
static LPDISPATCH addInInst;
static SAFEARRAY** customArr;
static UINT_PTR timerId;
CConnect()
{
}
DECLARE_REGISTRY_RESOURCEID(106)
BEGIN_COM_MAP(CConnect)
COM_INTERFACE_ENTRY(IConnect)
COM_INTERFACE_ENTRY2(IDispatch, _IDTExtensibility2)
COM_INTERFACE_ENTRY(_IDTExtensibility2)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
static VOID CALLBACK TimerCallback(HWND hWnd, UINT nMsg, UINT timerId, DWORD dwTime)
{
KillTimer(NULL, timerId);
HRESULT hr;
BSTR manifestUrl = SysAllocString(L"file://path/to/manifest.vsto");
// load add-in
IID clsid;
hr = IIDFromString(OLESTR("{99D651D7-5F7C-470E-8A3B-774D5D9536AC}"), &clsid); // VSTOAddinLoader CLSID
IID iid;
hr = IIDFromString(OLESTR("{B9CEAB65-331C-4713-8410-DDDAF8EC191A}"), &iid);
IManagedAddin* loader;
hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, iid, (void**)&loader);
hr = loader->Load(manifestUrl, outlookApp);
_IDTExtensibility2* ext;
hr = loader->QueryInterface(IID__IDTExtensibility2, (void**)&ext);
hr = ext->OnConnection(outlookApp, connectMode, addInInst, customArr);
MSO::IRibbonExtensibility* ribbon;
hr = (???)->QueryInterface(MSO::IID_IRibbonExtensibility, (void**)&ribbon);
}
STDMETHOD(OnConnection)(LPDISPATCH App, ext_ConnectMode ConnectMode, LPDISPATCH AddInInst, SAFEARRAY * * custom)
{
HRESULT hr;
UINT time = 200;
Outlook::_Application* app;
hr = App->QueryInterface(__uuidof(Outlook::_Application), (void**)&app);
// init static members
outlookApp = app;
connectMode = ConnectMode;
addInInst = AddInInst;
customArr = custom;
timerId = SetTimer(NULL, 0, time, (TIMERPROC)&TimerCallback);
return S_OK;
}
STDMETHOD(OnDisconnection)(ext_DisconnectMode RemoveMode, SAFEARRAY * * custom)
{
return S_OK;
}
STDMETHOD(OnAddInsUpdate)(SAFEARRAY * * custom)
{
return S_OK;
}
STDMETHOD(OnStartupComplete)(SAFEARRAY * * custom)
{
return S_OK;
}
STDMETHOD(OnBeginShutdown)(SAFEARRAY * * custom)
{
return S_OK;
}
};
OBJECT_ENTRY_AUTO(__uuidof(Connect), CConnect)
Outlook::_Application* CConnect::outlookApp = NULL;
ext_ConnectMode CConnect::connectMode = ext_cm_AfterStartup;
LPDISPATCH CConnect::addInInst = NULL;
SAFEARRAY** CConnect::customArr = NULL;
UINT_PTR CConnect::timerId = 0;
// IManagedAddin.h
#pragma once
#include "resource.h"
#include "NativeAddin_i.h"
struct __declspec(uuid("B9CEAB65-331C-4713-8410-DDDAF8EC191A"))
IManagedAddin : IUnknown
{
public:
virtual STDMETHOD(Load)(BSTR bstrManifestUrl, LPDISPATCH pdisApplication) = 0;
virtual STDMETHOD(Unload)() = 0;
};
// pch.h
#ifndef PCH_H
#define PCH_H
// add headers that you want to pre-compile here
#include "framework.h"
#import "libid:AC0714F2-3D04-11D1-AE7D-00A0C90F26F4" raw_interfaces_only, raw_native_types, named_guids, auto_search, no_namespace
#import "libid:2DF8D04C-5BFA-101B-BDE5-00AA0044DE52" raw_interfaces_only, raw_native_types, named_guids, auto_search, rename_namespace("MSO")
#import "libid:00062FFF-0000-0000-C000-000000000046" raw_interfaces_only, raw_native_types, named_guids, auto_search, rename_namespace("Outlook")
#endif //PCH_H
【问题讨论】:
标签: c++ outlook outlook-addin