How can I access the Integrated Development Environment (IDE) automation model from a VSIP Package?

With the release of the VSIP Extras, which builds on the VSIP SDK, accessing the IDE automation model from a VSIP Package (also referred to as VSPackage) is a snap. For more information on accessing the automation model, see Extending Managed VSPackages with Automation.


A lot of VSIP Packages are already implemented with unmanaged C++ and ATL. So what should a C++ programmer do?


A C++ programmer needs to carry out the following steps:


1. Retrieve the _DTE automation interface by calling QueryService on the IServiceProvider interface passed to your IVsPackage::SetSite method.

   pServiceProvider->QueryService(SID_SDTE, IID__DTE, (void**)pDTE);

SID_SDTE is the serviceID for the DTE automation service and IID__DTE is the interface ID for the _DTE interface. Both IDs are defined in DTEINTERNAL.H.
If you created your VSIP Package with the VSIP Package Wizard or from the BscPkg baseline sample, you can leverage the existing interface caching mechanism built into the CVsComModule object of your project. The CVsComModule object contains a number of helper methods, like GetIVsShell() and GetILocalRegistry() , that use the GetCachedI() method to retrieve the respective interface.

2. To extend GetCachedI() to retrieve the _DTE interface, first add the following helper function to your project’s CVsComModule class.
    _DTE* GetDTE(void)
return reinterpret_cast<_DTE*>(GetCachedI(eDTE));
You must alsoadd the data constant eDTE to the CVsComModule enum declaration.
    enum { // REQUIRED to stay in same order as two other structures
,eDTE // new enum for _DTE interface };
You must preserve the order of data constants in this enumerator, so be sure to add eDTE to the bottom of the list.


3. Finally, you must add an entry to the static QSPairs array. The GetCachedI() method uses the static QSPairs array to store the _DTE interface pointer. The SID_SDTE and IID__DTE IDs in this entry specify that the _DTE interface pointer is to be retrieved.

static QSPair g_rgqsPairs[] =
{ &SID_SVsShell, &IID_IVsShell, NULL }
,{ &SID_SVsUIShell, &IID_IVsUIShell, NULL }
,{ &SID_SVsSolution, &IID_IVsSolution, NULL }
,{ &SID_SVsHelp, &IID_Help, NULL }
,{ &SID_SLocalRegistry, &IID_ILocalRegistry, NULL }
,{ &SID_SUIHostLocale, &IID_IUIHostLocale2, NULL }
,{ &SID_SVsShellMonitorSelection, &IID_IVsMonitorSelection, NULL }
,{ &SID_SVsUIShellOpenDocument, &IID_IVsUIShellOpenDocument, NULL }
,{ &SID_SVsRunningDocumentTable, &IID_IVsRunningDocumentTable, NULL }
,{ &SID_SOleComponentUIManager, &IID_IOleComponentUIManager, NULL }
,{ &SID_SVsStatusbar, &IID_IVsStatusbar, NULL }
,{ &SID_SVsShellDebugger, &IID_IVsDebugger, NULL }
,{ &VxDTE::SID_SVsExtensibility, &VxDTE::IID_IVsExtensibility, NULL }
,{ &VxDTE::SID_SExtensionManager, &VxDTE::IID_ObjectExtenders, NULL }
,{ &SID_SDTE, &IID__DTE, NULL} // new entry for _DTE* interface

4. Finally, call the GetDTE( ) helper function on your global _Module object.

For example:
_DTE* pDTE = _Module.GetDTE();


Note that you can extend this pattern to include other useful VSIP interfaces, such as IVsObjBrowser and IVsClassView.


Cheers and happy coding!

Dr. eX