如何从命令行C ++ VSPackage

时间:2015-08-24 19:03:48

标签: c++ visual-studio envdte vspackage

我有一个仅限命令行的C ++ VSPackage。在我的pkgdef文件中设置以下Autoload注册表项, not 强制从命令行运行devenv时加载VSPackage。

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

但是,如果我添加命令行参数,我可以根据需要加载VSPackage:

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

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

问题在于,当我尝试在OnAfterOpenSolution事件中获取DTE对象时,它会失败。当我在GUI模式下运行devenv时,相同的代码可以正常工作。

是否有更好的方法可以让我的命令行vspackage在启动时加载,或者有没有办法使用上面的方法来获取DTE对象?

以下是我用来获取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;
}

1 个答案:

答案 0 :(得分:1)

我找到了问题的答案。您可以覆盖IVsPackageImpl :: SetSite()并在指定的IServiceProvider上使用QueryService来访问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);
}