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

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

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

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

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

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

        // --------------------------------------------------------------------------------------------/// <summary>/// Suggests a DTE2 object as the global service provider for SiteManager./// </summary>/// <param name="dte2">DTE2 object as a global service provider candidate.</param>// --------------------------------------------------------------------------------------------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是个什么东东?又是谁调用了这个方法呢?

    // --------------------------------------------------------------------------------------------/// <summary>/// Monikers of possible DTE objects. Right now VS 2008 and VS 2010 is handled./// </summary>// --------------------------------------------------------------------------------------------private static readonly List<string> VSMonikers =new List<string>{"!VisualStudio.DTE.9.0:{0}","!VisualStudio.DTE.10.0:{0}"};// --------------------------------------------------------------------------------------------/// <summary>/// The static constructor automatically tries to assign the SiteManager static class to a site/// that accesses VS IDE global services./// </summary>// --------------------------------------------------------------------------------------------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版本的方法呢?答案是:有,通过注册表。

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

        // --------------------------------------------------------------------------------------------/// <summary>/// Monikers of possible DTE objects. Right now VS 2008 and VS 2010 is handled./// </summary>// --------------------------------------------------------------------------------------------private static readonly IEnumerable<string> VSMonikers;// --------------------------------------------------------------------------------------------/// <summary>/// The static constructor automatically tries to assign the SiteManager static class to a site/// that accesses VS IDE global services./// </summary>// --------------------------------------------------------------------------------------------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;}}

附:修改后的VSXtra

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

【Visual Studio】在VS2012中使用VSXtra相关推荐

  1. OpenCV图像监视:在Visual Studio调试器中查看内存中图像

    OpenCV图像监视:在Visual Studio调试器中查看内存中图像 图像监视:在Visual Studio调试器中查看内存中图像 先决条件 安装 例子 更多的 图像监视:在Visual Stud ...

  2. Visual Studio 2019 preview中体验C# 8.0新语法

    准备工作: Visual Studio 2019 Preview版本中并没有包含所有的C# 8.0的新功能,但目前也有一些可以试用了.在开始之前,需要进行入两项设置: 将Framework设置为.ne ...

  3. 软件测试msf模型,Visual Studio 2010 Ultimate中MSF过程模型的设计

    Visual Studio 2010 Ultimate中MSF过程模型的设计 发表于:2010-04-06来源:作者:点击数: 过程模型是 软件工程 学中的一部分,就好比我们用什么过程方法进行软件&q ...

  4. 【转】Visual Studio 2005/2008中的快捷键与小技巧整理

    ---------------------------------------------------------------- 代码编写------------------------------- ...

  5. 【C++】在 Visual Studio 调试器中指定符号 (.pdb) 和源文件(转载自RSS翻译)

     在 Visual Studio 调试器中指定符号 (.pdb) 和源文件 查找并指定符号文件和源文件:指定符号加载行为.使用符号和源服务器:自动或按需加载符号.  内容 查找符号 (.pdb) ...

  6. 直接在Visual Studio代码编辑器中加密字符串文件

    String encryption is used everywhere in desktop & mobile software. You might not even know about ...

  7. Visual Studio 2022环境中C语言的使用——一维数组和二维数组

    我是荔园微风,作为一名在IT界整整25年的老兵,今天总结一下,Visual Studio 2022环境中,是如何使用C语言的数组的. 先说一维数组,直接上代码: 这里特别容易搞错的就是一维数组的初始化 ...

  8. Visual Studio 调试器中的转储文件

    Visual Studio 调试器中的转储文件 转储文件是一个快照,其显示某个时间点正在为应用执行的进程和已为应用加载的模块. 带堆信息的转储还包括该时间点的应用内存的快照. 在 Visual Stu ...

  9. 增强我们的Visual Studio(更新中)

    芭蕉的一篇文章<玩转Visual Studio ---Editor篇>让我想起了跟一个同事的争论. 这位同事是用Java的,最近的一个.NET项目中,他来帮我们做.所以他也开始使用VS20 ...

  10. Visual Studio 2008/2010中Xaml开发格式设置技巧

    在Silverlight和WPF项目开发中,经常要和Xaml语言打交道,大家都知道,一个清晰明了的开发语言布局可以让开发人员方便,快捷的阅读和理解代码,这里我介绍几个Xaml开发布局设计技巧. 这里我 ...

最新文章

  1. 机器学习模型部署都有哪些坑?
  2. Java基础第十三天总结
  3. ubuntu怎么测tcp协议的服务器,Ubuntu利用TCP协议来获取server时间(示例代码)
  4. Codeforces 1188E Problem from Red Panda (计数)
  5. django查询集-17
  6. 怎么看android sdk 文档
  7. 了解 Vue SSR 这一篇足以
  8. flutter 自定义键盘_入门级机械键盘选购对比
  9. import pandas as pd什么意思_Pandas万花筒:让绘图变得更美观
  10. win7电脑更改不了分辨率的解决方法
  11. 机器学习笔记(十二)——马尔科夫模型
  12. html绘制静态图表,怎样用JavaScript和HTML5 Canvas绘制图表
  13. oracle10g静默升级,Linux下静默安装,升级和删除Oracle10g客户端
  14. CountdownLatchTest
  15. MOOON-agent系统设计与使用说明
  16. Tableau Desktop【包含各个版本】
  17. Android Studio连接夜神模拟器
  18. SAS学习笔记5:删除字符串空格-left/right/trim/strip/compress/compbl等函数的比较
  19. Flink的“前世今生”
  20. Codeforces-715A-Plus and Square Root(找规律)

热门文章

  1. 推荐系统遇上深度学习(四)--多值离散特征的embedding解决方案
  2. Redis的N种妙用,不仅仅是缓存
  3. 空间滤波_第三章 灰度变换与空间滤波-(六)锐化空间滤波器之拉普拉斯算子...
  4. c语言作业帮,少训练大功课C语言
  5. android ripple 大小,Android L限制Ripple水波纹范围大小
  6. 清理神器CleanMyMac X 空间透镜——可视化您的磁盘空间
  7. centos7.x设置nginx开机自启动
  8. BZOJ4545: DQS的trie 广义后缀自动机_LCT
  9. cpu高 load 高 内存高 io 高怎么排查
  10. linux系统中-E,-S,-c的区别和作用(怎么讲代码转化为机器识别的语言)