博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Visual Studio】在VS2012中使用VSXtra
阅读量:6176 次
发布时间:2019-06-21

本文共 6171 字,大约阅读时间需要 20 分钟。

最近工作中需要把之前为VS 2010写的扩展迁移到VS 2012上。在将工程版本改为VS2012之后,代码没有修改,直接编译通过,也可以安装到VS2012上。

不过,在实际使用的时候,却报错,提示“The framework has not been sited!”。调试后发现,这个错误是我们在IDE开发中用到的报出的。错误的报错位置是在SiteManager的GetGlobalService方法中:

// --------------------------------------------------------------------------------------------        ///         /// Gets a global service with the specified address and behavior type.        ///         /// 
Address type of the service
///
Behavior (endpoint) type of the service
///
The service instance obtained.
// -------------------------------------------------------------------------------------------- public static TInterface GetGlobalService
() where TInterface : class where SInterface : class { if (!HasGlobalServiceProvider) throw new InvalidOperationException("The framework has not been sited!"); var ti = GlobalServiceProvider.GetService
(); if (ti == null) throw new NotSupportedException(typeof(SInterface).FullName); return ti; }

从代码可以看到,异常抛出的条件是在GlobalServiceProvider不存在的时候。那么这个HasGlobalServiceProvider属性是什么样的呢:

// --------------------------------------------------------------------------------------------        ///         /// Gets the flag indicating if the SiteManager has already a global service provider or not.        ///         // --------------------------------------------------------------------------------------------        public static bool HasGlobalServiceProvider        {            get { return (GlobalServiceProvider != null); }        }

看来是判断GlobalServiceProvider是否为null。那么,是谁负责设置这个GlobalServiceProvider的呢?我们通过Find All References可以发现这个属性是在SuggestGlobalServiceProvider方法中被设置的,这个方法有多个重载,跟踪一下,需要调用到的是这个:

// --------------------------------------------------------------------------------------------        ///         /// Suggests a DTE2 object as the global service provider for SiteManager.        ///         /// DTE2 object as a global service provider candidate.        // --------------------------------------------------------------------------------------------        public static void SuggestGlobalServiceProvider(DTE2 dte2)        {            SuggestGlobalServiceProvider(dte2 as IOleServiceProvider);        }

而这个SuggestGlobalServiceProvider则是在一个叫做TryToGetServiceProviderFromCurrentProcess的关键方法中被调用到的(部分代码省略):

private static void TryToGetServiceProviderFromCurrentProcess(string vsMoniker)        {            ......            string ideMoniker = String.Format(vsMoniker, Process.GetCurrentProcess().Id);            ......            while (enumMoniker.Next(1, moniker, IntPtr.Zero) == 0)            {                string displayName;                moniker[0].GetDisplayName(ctx, moniker[0], out displayName);                if (displayName == ideMoniker)                {                    // --- Got the IDE Automation Object                    Object oDTE;                    rot.GetObject(moniker[0], out oDTE);                    dte = oDTE as DTE2;                    if (dte != null) break;                }            }            SuggestGlobalServiceProvider(dte);        }

其大概意思是从当前进程中获取一些信息,跟通过传入的vsMoniker格式化之后的一个字符串进行比对,如果名字是一样的,则通过它获取VS IDE的DTE实例。那么,这个vsMoniker是个什么东东?又是谁调用了这个方法呢?

// --------------------------------------------------------------------------------------------    ///     /// Monikers of possible DTE objects. Right now VS 2008 and VS 2010 is handled.    ///     // --------------------------------------------------------------------------------------------    private static readonly List
VSMonikers = new List
{ "!VisualStudio.DTE.9.0:{0}", "!VisualStudio.DTE.10.0:{0}" }; // -------------------------------------------------------------------------------------------- ///
/// The static constructor automatically tries to assign the SiteManager static class to a site /// that accesses VS IDE global services. /// // -------------------------------------------------------------------------------------------- static SiteManager() { foreach (string moniker in VSMonikers) { TryToGetServiceProviderFromCurrentProcess(moniker); if (HasGlobalServiceProvider) return; } }

看到这儿,我们也明白了,敢情VSXtra这儿写死了几个字符串{ "!VisualStudio.DTE.9.0:{0}", "!VisualStudio.DTE.10.0:{0}" },跟VS版本相关,而VS2012的版本号是11,这里没有,所以当然找不到DTE Instance了。

最简单的修改版本,添加一个VS2012的版本号:"!VisualStudio.DTE.11.0:{0}",运行测试OK。

不过,对于这种hard-code的写法笔者是看着很不爽,那么,有没动态获取已经安装的VS版本的方法呢?答案是:有,通过注册表。

于是最后的代码修改如下:

// --------------------------------------------------------------------------------------------        ///         /// Monikers of possible DTE objects. Right now VS 2008 and VS 2010 is handled.        ///         // --------------------------------------------------------------------------------------------        private static readonly IEnumerable
VSMonikers; // -------------------------------------------------------------------------------------------- ///
/// The static constructor automatically tries to assign the SiteManager static class to a site /// that accesses VS IDE global services. /// // -------------------------------------------------------------------------------------------- static SiteManager() { var vsRegKey = Registry.CurrentUser .OpenSubKey("Software") .OpenSubKey("Microsoft") .OpenSubKey("VisualStudio"); var installedNames = vsRegKey.GetSubKeyNames().Where(x => !x.Contains("Exp") && !x.Contains("_Config")); VSMonikers = installedNames.Select(x => "!VisualStudio.DTE." + x + ":{0}").ToArray(); foreach (string moniker in VSMonikers) { TryToGetServiceProviderFromCurrentProcess(moniker); if (HasGlobalServiceProvider) return; } }

附:

转载于:https://www.cnblogs.com/RMay/p/VSXtra_for_VS2012.html

你可能感兴趣的文章
认证模式之SSL模式
查看>>
PgSQL · 最佳实践 · 双十一数据运营平台订单Feed数据洪流实时分析方案
查看>>
如何在 Linux 中统计一个进程的线程数
查看>>
NVIDIA新作解读:用GAN生成前所未有的高清图像(附PyTorch复现) | PaperDaily #15
查看>>
CString、CTime和COleDateTime转换
查看>>
在linux虚机中装vmtools
查看>>
梅森素数--美丽的贝壳
查看>>
WCF技术剖析之十三:序列化过程中的已知类型(Known Type)
查看>>
linux设备驱动程序--类class的实现
查看>>
中国云计算应用进入集中爆发期
查看>>
算法精解---计数排序
查看>>
DockOne微信分享(一二八):容器如何监控?
查看>>
谈谈分布式事务(Distributed Transaction)[共5篇]
查看>>
如何确保快递“最后一公里” ,亚马逊打算送到你的汽车后备箱
查看>>
Gartner:财务应用迁移到云 速度超出预期
查看>>
阿里云向物流业渗透 货运司机受益
查看>>
灾难恢复的人为因素:经理们应该做的10件事情
查看>>
中国教育行业可能到了最不平凡的10年:要么创新,要么死亡
查看>>
自然语义分析下的大数据商业化之道
查看>>
大数据开启智能交通之路
查看>>