Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MSBuildWorkspace.OpenProjectAsync throws InvalidOperationException when invoked from custom MsBuild task #14206

Closed
per-samuelsson opened this issue Sep 30, 2016 · 19 comments
Assignees
Labels
Milestone

Comments

@per-samuelsson
Copy link

I havent found anywhere you wouldn't support this scenario, and even though its a bit on the exotic side, I'll report it in case you want to dig into it.

Steps to Reproduce:

  1. Create a custom MsBuild task in a standard C# library, e.g. similar to this.
  2. In Execute(), add the code below.
  3. Invoke it from a project (standard Console Application will do fine).

In Task.Execute()

var ws = MSBuildWorkspace.Create();
var project = ws.OpenProjectAsync("C:\path\to\some\standard\project.csproj").Result;

Expected Behavior:
A new Project instance.

Actual Behavior:
An (aggregated) InvalidOperationException:

System.AggregateException was unhandled by user code
  HResult=-2146233088
  Message=One or more errors occurred.
  Source=mscorlib
  StackTrace:
       at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
       at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
       at System.Threading.Tasks.Task`1.get_Result()
       at App1.ProjectWeaver..ctor(String projectFilePath) in C:\Users\Per\proj\RoslynWorkspaceLabs\App1\ProjectWeaver.cs:line 89
       at App1.ProjectFileWeaver.Execute() in C:\Users\Per\proj\RoslynWorkspaceLabs\App1\ProjectWeaver.cs:line 28
       at WeaverTasks.WeaverProtoTask.Execute() in C:\Users\Per\proj\RoslynWorkspaceLabs\WeaverTasks\WeaverProtoTask.cs:line 74
       at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
       at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()
  InnerException: 
       HResult=-2146233079
       Message=Cannot open project 'C:\Users\Per\proj\RoslynWorkspaceLabs\ConsoleApplication1\ConsoleApplication1.csproj' because the language 'C#' is not supported.
       Source=Microsoft.CodeAnalysis.Workspaces.Desktop
       StackTrace:
            at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.ReportFailure(ReportMode mode, String message, Func`2 createException)
            at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.TryGetLoaderFromProjectPath(String projectFilePath, ReportMode mode, IProjectFileLoader& loader)
            at Microsoft.CodeAnalysis.MSBuild.MSBuildProjectLoader.<LoadProjectInfoAsync>d__20.MoveNext()
         --- End of stack trace from previous location where exception was thrown ---
            at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
            at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
            at Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.<OpenProjectAsync>d__19.MoveNext()
       InnerException: 

More:
If I do the same in a separate process / standard application, it works like a charm.

@per-samuelsson
Copy link
Author

Seem to be related to #2779 and #4127.

Also: version used:

Microsoft (R) Build Engine version 14.0.25123.0

@per-samuelsson
Copy link
Author

Oh, and expanding on this:

  1. Invoke it from a project (standard Console Application will do fine).

Doesn't have to be VS. I'm using just MsBuild myproj.csproj.

@svick
Copy link
Contributor

svick commented Sep 30, 2016

I get the same exception when I run your code from a console application which references Microsoft.CodeAnalysis.Workspaces.Common (which contains MSBuildWorkspace), but not Microsoft.CodeAnalysis.CSharp.Workspaces. Are you sure you are referencing Microsoft.CodeAnalysis.CSharp.Workspaces?

@daveaglick
Copy link
Contributor

I ran into similar problems in Scripty. It's actually an MSBuild limitation - you can't run one build from within another. @AArnott has a definitive explanation here: #4974 (comment)

I worked around it by launching a separate process from inside the task to perform the Roslyn work that creates a workspace: https://github.com/daveaglick/Scripty/blob/f02ce93c7b3c7a75885497290e6310720b88568f/src/Scripty.MsBuild/ScriptyTask.cs#L67

@per-samuelsson
Copy link
Author

I worked around it by launching a separate process from inside the task to perform the Roslyn work that creates a workspace.

@daveaglick
That was the exact same workaround I used. And that works. Just thought it was something the Roslyn team would wan't to look at.

Are you sure you are referencing Microsoft.CodeAnalysis.CSharp.Workspaces?

@svick
From the custom MsBuild you mean? No I'm not. I just noticed it didn't work in one context, and worked fine in another. And since both compiled fine ... well, I didn't consider that.

@svick @daveaglick

Really appreciate the feedback. Thanks.

@jasonmalinowski
Copy link
Member

@per-samuelsson: What ultimate thing are you trying to build here? We've generally been of the opinion (as you've noted) to "not do that", since there's a lot of challenges and might be other hookups available.

@per-samuelsson
Copy link
Author

@per-samuelsson: What ultimate thing are you trying to build here? We've generally been of the opinion (as you've noted) to "not do that", since there's a lot of challenges and might be other hookups available.

We are trying to get Starcounter to level-up to .NET Core. As part of that, we need to continue support our development model that has always been based on something we usually refer to as weaving.

In previous versions, we've always done this on IL (binary) level, transforming .NET assemblies on the fly. With the launch of Roslyn ("compiler as a service") a few years ago, it was kind of like Christmas for us (rationale: IL-weaving is not very funny).

However, we've got somewhat disappointed over time. From our perspective, what has happened is that yes, Roslyn has made compiling go from a black-box to something you can enjoy the services of. But at the same time, no, it's still a black-box in the sense that .NET Core does not support any way to really get involved in compiling of user code. There is just no way to hook into that.

As I wrote in #10882 a couple of months ago, we got pretty bruised by you guys dropping the support for ICompileModule (part of deprecated DNX), since we had our weaver successfully ported to that and was on a good track at that time.

Then it seemed source generators would be the thing that kind of would enable a (more restricted) similar experience, and we started tracking that and prototyping on it (again, see #10882).

However, then at some point it was no longer part of C# 7.0 and now like several times per week, I try to see if there is some activity on that, but the track seems just dead and nothing new happens (i.e. no new issue activity on Original/Replace since like July and no new commits in that feature branch either).

With our customers increasingly interested in .NET Core and we want to support more platforms, we've found ourselves in a position where we just can't wait any more. Hence, we are trying to be as broad and open as possible, trying to find ways to realize this thing, and one of those is turning to some MsBuild + Roslyn workspaces solution.

It's also somewhat a result of your planning to drop project.json, turning to MsBuild, which also is a bit hard to cope with when you try to retarget a product such as ours to .NET Core.

@Pilchie
Copy link
Member

Pilchie commented Oct 17, 2016

@mattwar can you comment on this, having looked into both generators and msbuildworkspace the most?

@Pilchie Pilchie added this to the 2.0 (RC) milestone Oct 17, 2016
@mattwar
Copy link
Contributor

mattwar commented Oct 17, 2016

@per-samuelsson instead of using MsbuildWorkspace you can use CommandLineProject with AdHocWorkspace. You'll have to pass all the same arguments into your target that the csc target has and convert them to command line arguments. The result will be the same as if you used MsbuildWorkspace but without using msbuild recursively.

@per-samuelsson
Copy link
Author

@mattwar

Thanks for the feedback and the hints. I'll review and try that approach eventually for sure.

@per-samuelsson
Copy link
Author

@mattwar,

Short follow-up: what about getting those workspace bits running x-plat, will/should it work?

Reason I'm asking is I'm getting some weird restore problems on RC3 when bringing anything but standard CodeAnalysis in. Could o/c very well be on my part though, not skilled enough setting that up properly.

@per-samuelsson
Copy link
Author

Short follow-up: what about getting those workspace bits running x-plat, will/should it work?

Hm, looks like I've been bit by #16040. I'll see if I can understand a way to work around it.

@per-samuelsson
Copy link
Author

per-samuelsson commented Feb 8, 2017

Hm, looks like I've been bit by #16040. I'll see if I can understand a way to work around it.

I was able to restore by using the workaround suggested in the OP of referenced issue, but still seem unable to access CommandLineProject type.

I now studied its code, and also noticed that when restored, the only home of CommandLineProject is in Microsoft.CodeAnalysis.Workspaces.Desktop.dll, which in turn is under a net46 hive in packages cache.

I guess that mean no x-plat for CommandLineProject right? 😕

@mattwar
Copy link
Contributor

mattwar commented Feb 8, 2017

Yes, that means CommandLineProject is not x-plat. I suspect there is no longer any reason why it couldn't be. A lot of the code in this desktop project no longer needs to be there.

@per-samuelsson
Copy link
Author

Yes, that means CommandLineProject is not x-plat.

Ouch. Then that path is unfortunately dead for us, as our main objective going .NET Core is being able to offer our product on more platforms. To bad, because I was really getting increasingly exited with the solution you proposed.

Thanks for the feedback.

@per-samuelsson
Copy link
Author

@mattwar

Since we are yet again in a position where we need to find a way going forward on our .NET Core path, can I just ask another thing regarding:

Yes, that means CommandLineProject is not x-plat.

That would mean that at this point, using Roslyn workspaces (including CommandLineProject, MsBuildWorkspace, AdHocWorkspace) are Windows only? For me, those things was kind of the enabler for what @CyrusNajmabadi suggested instead of using source generators during the discussion back in December at #5561. (Even though I guess you could do without them, but it seem a lot harder, especially regarding how to properly derive at a semantic model based on given meta references).

So, if those things are in fact Windows-specific, is there any place I could vote for it to be a prio to address that (given you hinted they might not even had to be any more)?

cc @CyrusNajmabadi

@Pilchie
Copy link
Member

Pilchie commented Feb 10, 2017

AdHocWorkspace should work cross-platform. We don't currently have MSBuildWorkspace or CommandLineProject working cross-platform.

I expect it's something that we will do at some point, but I'm not exactly sure how that will shake out yet, since both use some Windows specific code (like DesktopAssemblyIdentityComparer in CommandLineProject and we don't currently use the .NET Core version of MSBuild in MSBuildWorkspace.

@per-samuelsson
Copy link
Author

Thanks @Pilchie. That certainly get me one step further.

MsBuildWorkspace I've abandoned really, as well as source generators. Now I know I could use AdHocWorkspace (I tried experimenting with it, and seem to work).

If I still would want to give CommandLineProject a try (even knowing it's NetFramework only at this point), can you hint me on how? Thing is, I've set up this .Core RC3 project, setup a package reference to Microsoft.CodeAnalysis.Workspaces.Common, but cant seem to access that class. I guess because it hides under that lib/net46/ (I peaked this "assets" file)? It's not obvious for me what I need to do to use it. 😕

@per-samuelsson
Copy link
Author

If I still would want to give CommandLineProject a try (even knowing it's NetFramework only at this point), can you hint me on how? Thing is, I've set up this .Core RC3 project, setup a package reference to Microsoft.CodeAnalysis.Workspaces.Common, but cant seem to access that class. I guess because it hides under that lib/net46/ (I peaked this "assets" file)? It's not obvious for me what I need to do to use it. 😕

Aha, found out my self by thinking a little (and being lucky): it's about the target framework of course. Those lib/net46 bits will not be brought in unless I retarget to net46 or higher.

Then again, thanks, and I have no more questions at this point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants