最近工作中需要把之前为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 : class
where 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(, moniker, IntPtr.Zero) == )
{
string displayName;
moniker[].GetDisplayName(ctx, moniker[], out displayName);
if (displayName == ideMoniker)
{
// --- Got the IDE Automation Object
Object oDTE;
rot.GetObject(moniker[], 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

【Visual Studio】在VS2012中使用VSXtra的更多相关文章

  1. 在Visual Studio for Mac中使用fastlane管理iOS的provision

    Xamarin开发中,最烦的就是provision的管理了. 全手工的话,要先创建一个key,上传后生成cert文件,再创建provision.如果在手机上调试,还要把手机加到provision中去. ...

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

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

  3. 在 Visual Studio for Mac 中编译和生成

    使用Visual Studio将C#生成DLL文件的方法 https://www.cnblogs.com/AaronBlogs/p/6840283.html Visual Studio 开发 - Vi ...

  4. 记录visual Studio使用过程中的两个问题

    Visual Studio是Windows平台下进行项目管理和开发的终极利器.除了微软自家的技术外,新版的VS不但支持Javascript, Python的开发调试,甚至还支持了Android, iO ...

  5. 在Visual Studio 2015 Preview 中使用Github 版本控制

    打开Visual Studio,新建项目,右下角勾选,如下图: 点击‘OK’后,出现下图窗口,选择'Git' : 如果是现有项目可以在‘文件’菜单下找到‘Add to Source Control’ ...

  6. 如何通过PowerShell在Visual Studio的Post-build中预热SharePoint站点

    问题现象 Visual Studio在开发SharePoint的时候,发布部署包后,首次打开及调试站点页面的时候会非常的慢 解决方案 使用PowerShell脚本,加载SharePoint插件后遍历所 ...

  7. Visual Studio 2015 RC中的ASP.NET新特性和问题修正

    (此文章同时发表在本人微信公众号"dotNET每日精华文章") 微软在Build大会上发布了Visual Studio 2015 RC,这也预示着Visual Studio 201 ...

  8. 在Visual Studio 2010/2012中 找不到创建WebService的项目模板

    参考文章: http://blog.sina.com.cn/s/blog_6d545999010152wb.html 在 Visual Studio 2010 或者2012的新建 Web 应用程序或者 ...

  9. 在 Visual Studio 调试器中指定符号 (.pdb) 和源文件

    查找并指定符号文件和源文件:指定符号加载行为.使用符号和源服务器上:加载符号自动或在要求.   内容 查找符号 (.pdb) 文件 查找源文件   查找符号 (.pdb) 文件 说明 在之前的 Vis ...

  10. Visual Studio属性配置中使用宏

    在学习C语言的时候,我们曾经遇到过一个宏的概念.宏的作用机理本质上是宏的展开,C语言中的宏的用法也有很多种(水其实很深...),不过从感觉上来讲,人们大致上会在以下的场景中,利用宏来解决一些窘境:一是 ...

随机推荐

  1. mysql大小写问题

    以前做企业项目的时候,用的都是oracle数据库,在新公司项目用的是mysql,有关mysql大小写的问题 1   windows下默认mysql是不区分大小写的,要想让其支持大小写.更改方法 在my ...

  2. uniq

    -c, --count 在每行前加上表示相应行目出现次数的前缀编号-d, --repeated 只输出重复的行-D, --all-repeated[=delimit-method 显示所有重复的行de ...

  3. Astyle编程语言格式化工具的中文说明

    Artistic Style 1.23Maintained by: Jim PatteeOriginal Author: Tal Davidson Usage  :  astyle [options] ...

  4. 动手学习TCP:数据传输

    前面的文章介绍了TCP状态变迁,以及TCP状态变迁图中的一些特殊状态. 本文主要看看TCP数据传输过程中需要了解的一些重要点: MSS(Maximum Segment Size) Seq号和Ack号的 ...

  5. [转]jquery Fancybox丰富的弹出层效果

    本文转自:http://www.helloweba.com/view-blog-65.html Fancybox是一款优秀的jquery插件,它能够展示丰富的弹出层效果.前面我们有文章介绍了facyb ...

  6. 【C#】3.算法温故而知新 - 快速排序

    快速排序相比冒泡排序,每次交换是跳跃式的.每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数放到基准点的右边.这样每次交换的时候就不会像冒泡排序一样只能在相邻 ...

  7. hihoCoder #1388 : Periodic Signal ( 2016 acm 北京网络赛 F题)

    时间限制:5000ms 单点时限:5000ms 内存限制:256MB 描述 Profess X is an expert in signal processing. He has a device w ...

  8. 如何解决inline-block元素的空白间距

    早上在博客中有人提了这样一个问题:“li元素inline-block横向排列,出现了未知间隙”,我相信大家在写页面的时候都遇到过这样的情况吧. 我一般遇到这情况都会把li浮动起来,这样就没有间隙.但是 ...

  9. 2014 Super Training #10 G Nostop --矩阵快速幂

    原题: FZU 2173 http://acm.fzu.edu.cn/problem.php?pid=2173 一开始看到这个题毫无头绪,根本没想到是矩阵快速幂,其实看见k那么大,就应该想到用快速幂什 ...

  10. npm install时报错 npm ERR!Windows_NT 6.1.7601

    解决办法:先设置代理为空 npm config set proxy null, 然后再npm install cnpm -g --registry=https://registry.npm.taoba ...