6

For my master thesis I'm building a Visual Studio plugin that should perform some code-analysis of the current opened solution. In order to do that I've decided to try to use Roslyn, using the corresponding nuget package.

Everything works fine (SyntaxTree for navigating the code,...) until I've tried to use MSBuildWorkspace.Create(). This last call causes the following exception:

Could not load file or assembly 'Microsoft.Build, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.":"Microsoft.Build, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a

I found this two posts:

from which I understand that I need the MSBuild Tools for Visual Studio 14, which is in the related iso.

I do not want to install the full Visual Studio 14, this also because the plugin that I'm writing should run under Visual Studio 2013. From the two post it seems that I can install only this part of VS 14.

My question actually is: if I install MSBuild Tools for Visual Studio 14 what will happen with all other Visual Studio projects that I'm currently working on? At the moment they use the MSBuild tool of Visual Studio 2013. It's possible to still use that?

Update

What I'm acctually trying to get is to find if a given method has references inside the project. The idea was to proceed as in this post.

Community
  • 1
  • 1
Lando
  • 103
  • 1
  • 9
  • Diagnostics that integrate with VS are going to be coupled to VS. It looks like Roslyn now requires VS 14 and the VS 13 preview is no longer supported. You certainly can install multiple versions of VS side-by-side but because it is CTP, there's always something that can go wrong. The usual boilerplate: "Although these CTPs are intended to be installed side-by-side together with earlier versions of Visual Studio, complete compatibility of every CTP is not guaranteed." – Mike Zboray Oct 12 '14 at 08:56
  • The fact that I can install side-by-side different VS versions (with the usual boilerplate) it's weel known to me. The fact is that at the end the plugin should work with Wisual Studio 2013. If, in order to work with VS 2013, I need to instal the MSBuild of VS 2014 that's not a problem until the "normal VS 2013 projects" will still use the old MSBuild. – Lando Oct 12 '14 at 11:06
  • 1
    As Jason says, you should use the VisualStudioWorkspace and you won't have any of these problems. As VisualStudioWorkspace is undocumented, I've written a guide to the various workspaces here: http://joshvarty.wordpress.com/2014/09/12/learn-roslyn-now-part-6-working-with-workspaces/ – JoshVarty Oct 12 '14 at 19:45

4 Answers4

6

When you say you're building a plugin for Visual Studio, if all you care about is getting the workspace for the currently open solution (i.e. the code the user is editing), you shouldn't use MSBuildWorkspace, really ever. That's a type for loading things outside of Visual Studio. What you can do if you're in the product is MEF [Import] Microsoft.VisualStudio.LanguageServices.VisualStudioWorkspace. That gives you live access to what the user has open, and avoids running MSBuild entirely.

Note you're still going to have to be careful about your choice of reference assemblies you build against: if you use the latest NuGet packages that won't work since those will differ in version (and also APIs -- we changed a bunch of stuff) than what was in the last Visual Studio 2013 preview.

Jason Malinowski
  • 18,148
  • 1
  • 38
  • 55
  • Using VisualStudioWorspace it's possible then to get the project and call `project.GetCompilationAsync().Result;`? – Lando Oct 13 '14 at 11:56
  • 1
    (Please, to better understand this question, see the update of my original question with the ultime goal that I'm trying to achieve.) – Lando Oct 13 '14 at 12:04
  • @Lando: Don't use `.Result`; use `await`. (otherwise, you will get deadlocks & other issues) – SLaks Oct 13 '14 at 13:40
  • Lando: yep, both VisualStudioWorkspace and MSBuildWorkspace derive from the same core type. The only difference is where the information comes from. – Jason Malinowski Oct 14 '14 at 02:20
  • @SLaks: for Roslyn we ensure our returned tasks are never scheduled to the UI thread so .Result is safe. That said, yes, users hate blocked threads. :-) – Jason Malinowski Oct 14 '14 at 02:20
  • @JasonMalinowski: can you please explain me what you mean with the second part of your original answer(the part about nuget)? What would be a better solution? – Lando Oct 15 '14 at 05:36
  • Just as a warning, the latest versions of the NuGet packages reflect the latest APIs which match the latest preview/CTP of Visual Studio "14". We're still evolving those APIs and so if you're trying to run stuff in Visual Studio 2013 and the old Roslyn preview for that, the APIs might not match and you'll run into various problems. We intend to eventually lock our APIs so you don't have this problem, but until then you might need to be very conscientious about which versions of the NuGet packages you reference. – Jason Malinowski Oct 15 '14 at 20:30
5

The issue is that (unfortunately) the assemblies in the public Roslyn nuget packages have been compiled with a newer version of MSBuild than what you want.

However, it's pretty simple to fix so that it works on MSBuild 4.0 (VS2012+). I've provided them with a PR with the fix (at https://roslyn.codeplex.com/workitem/405), but also published a nuget package called DesktopAnalysis that contains all the assemblies for doing C# code analysis, that work on VS2012+ (MSBuild 4.0+): https://www.nuget.org/packages/DesktopAnalysis

Just do an install-package DesktopAnalysis -pre instead and you're done. The assemblies are the same, the code is the same, etc.

I'm using this to provide a code migration extension that works from VS2013 all the way to VS2015 Preview.

kzu
  • 1,795
  • 15
  • 16
3

You could fork the Roslyn codebase, and compile with MSBUILD12 defined, which should still work, though we don't really test this much.

Kevin Pilch
  • 11,485
  • 1
  • 39
  • 41
1

This is entirely possible, but not at all easy.

You need to make sure that you only ever load the version of the Roslyn assemblies that is in the VS version you're targeting, by removing those assemblies from your VSIX and handling AssemblyResolve to make sure you get the right ones.
You can see my code that does exactly that here, and you can read more about this technique in my blog post

Note that if you need to [Export] any interfaces defined in Roslyn assemblies, this will not work at all, since MEF will try to load them before you add your handler. (unless you add a module initializer by hand in ildasm)

The harder part is that you need to limit yourself to the intersection of the APIs in every Roslyn version you want to support.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • I grimace seeing that code, and can't recommend it. Hooking AssemblyResolve is a messy way to do it -- and imagine if two extensions try doing that, each trying to load different versions of Roslyn! I recognize that they might have been unavailable in your particular case, but I also would put a comment in that code to indicate that if anybody needs a binding redirect or something, they shouldn't do that and use a supported mechanism. – Jason Malinowski Oct 12 '14 at 19:34
  • @JasonMalinowski: The point of that code is to load the version of Roslyn within VS; loading a different version of Roslyn is a bad idea. I don't know of any alternative to my code to make a single DLL work with VS2013 and Dev14. – SLaks Oct 12 '14 at 19:37
  • But what happens when two people do that? :-) – Jason Malinowski Oct 12 '14 at 22:51
  • @JasonMalinowski: It will work perfectly fine; they both redirect the load to the current VS version. – SLaks Oct 12 '14 at 23:53
  • Unless your Assembly.Load picks up a local copy somebody put in the binding path. But I guess you're already broken in that case. In any case, we should add binding redirects so you don't have to do this... – Jason Malinowski Oct 13 '14 at 03:54
  • @JasonMalinowski: Yes; it would be wonderful if you could add binding redirects. But it wouldn't help for the VS2013 Preview (unless you release another version of it?) – SLaks Oct 13 '14 at 13:40