2015-08-24 1 views
1

J'ai un C++ VSPackage en ligne de commande uniquement. Définir la clé de Registre Autoload suivante dans mon fichier pkgdef, pas forcer le VSPackage à être chargé lors de l'exécution de devenv à partir de la ligne de commande.Comment obtenir l'objet DTE à partir de la ligne de commande C++ VSPackage

[$RootKey$\AutoLoadPackages\{ADFC4E64-0397-11D1-9F4E-00A0C911004F}] 
"{75726504-cacb-4781-b384-63815a289e0a}"=dword:00000000 
@="UICONTEXT_NoSolution" 

Cependant, si j'ajoute un paramètre de ligne de commande, je peux obtenir le VSPackage pour charger au besoin:

[$RootKey$\AppCommandLine] 
"vsp"="{75726504-cacb-4781-b384-63815a289e0a}" 

[$RootKey$\AppCommandLine\vsp] 
"Arguments"="0" 
"DemandLoad"=dword:00000001 
"Package"="{75726504-cacb-4781-b384-63815a289e0a}" 
"HelpString"="#102" 

Le problème est que lorsque je tente d'obtenir l'objet DTE dans le OnAfterOpenSolution événement, il échoue. Le même code fonctionne quand je cours devenv en mode GUI.

Existe-t-il un meilleur moyen de charger la commande vspackage au démarrage, ou existe-t-il un moyen d'obtenir l'objet DTE en utilisant la méthode que j'utilise ci-dessus?

Voici le code que j'utilise pour obtenir DTE:

CComPtr<EnvDTE::_DTE> SinkSolutionEvents::GetDTE(CString program) 
{ 
    CString rotEntry; 
    rotEntry.Format(L"!VisualStudio.DTE.14.0:%d", program, GetCurrentProcessId()); 

    IRunningObjectTable *rot = NULL; 
    GetRunningObjectTable(0, &rot); 
    IEnumMoniker *enumMoniker; 
    rot->EnumRunning(&enumMoniker); 
    enumMoniker->Reset(); 
    ULONG fetched = 0; 
    IMoniker *moniker = NULL; 
    while (enumMoniker->Next(1, &moniker, &fetched) == 0) 
    { 
     IBindCtx *bindCtx = NULL; 
     CreateBindCtx(0, &bindCtx); 
     LPOLESTR pwszName; 
     HRESULT hr = moniker->GetDisplayName(bindCtx, NULL, &pwszName); 
     CString displayName; 
     if (SUCCEEDED(hr)) { 
      displayName = pwszName; 
      CoTaskMemFree(pwszName); 
      if (displayName == rotEntry) 
      { 
       CComPtr<IUnknown> punk; 
       rot->GetObject(moniker, &punk); 
       CComPtr<EnvDTE::_DTE> dte; 
       dte = punk; 
       return dte; 
      } 
     } 
    } 
    return NULL; 
} 
+0

vous ne parvenez pas à relier bindCtx, moniker et pourriture. convertissez-les en CComPtr <> pour éviter ces fuites. –

Répondre

1

J'ai trouvé la réponse à ma question. Vous pouvez remplacer IVsPackageImpl :: SetSite() et utiliser QueryService sur l'IServiceProvider spécifié pour accéder à EnvDTE.

HRESULT STDMETHODCALLTYPE MyVSPackage::SetSite(__RPC__in_opt IServiceProvider *pSP) 
{ 
    CComPtr<EnvDTE::_DTE> m_pDTE = NULL; 
    HRESULT hr = pSP->QueryService(SID_SDTE, IID__DTE, (void **)&m_pDTE); 
    return IVsPackageImpl::SetSite(pSP); 
}