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 and WPF Projects #2779

Closed
JoshVarty opened this issue May 15, 2015 · 25 comments
Closed

MSBuildWorkspace and WPF Projects #2779

JoshVarty opened this issue May 15, 2015 · 25 comments
Labels
Area-IDE Feature Request Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on. Verification Not Required

Comments

@JoshVarty
Copy link
Contributor

I'm trying to compile a WPF project using MSBuildWorkspace. Should this work out of the box, or do I need to do anything special to set it up?

When I open a .sln containing a WPF project and try to compile I receive two errors:

C:\Users\Josh\Documents\GitHub\Orange\WpfApplication1\WpfApplication1\MainWindow.xaml.cs(25,13): error CS0103: The name 'InitializeComponent' does not exist in the current context

and

error CS5001: Program does not contain a static 'Main' method suitable for an entry point

To reproduce, simply create a new WPF project. (Mine was WPFApplication1.sln). Then just load into a workspace and try to compile the project.

var msws = MSBuildWorkspace.Create(new Dictionary<string, string> { { "CheckForSystemRuntimeDependency", "true" } });
var soln = msws.OpenSolutionAsync(@"C:\Users\Josh\Documents\GitHub\Orange\WpfApplication1\WpfApplication1.sln").Result;
var comp = soln.Projects.First().GetCompilationAsync().Result;
var errs = comp.GetDiagnostics().Where(n => n.Severity == DiagnosticSeverity.Error).ToList();
//Two errors :(
@Pilchie
Copy link
Member

Pilchie commented May 15, 2015

We'll need to figure out what msbuild targets need to run in order to ensure that the markup compiler runs and generates the .g.cs files for this to work.

@mattwar
Copy link
Contributor

mattwar commented May 15, 2015

This is caused by two problems.

The first is that msbuild workspace is invoking msbuild with the "Compile" target that does not include any of the xaml tasks. It needs to use at least the "CoreBuild" task to get the xaml compilers to run and generate the extra files. This is easy to change.

The second is that the xaml tasks are bounds to earlier msbuild version than msbuild workspace is using and need redirecting to function correctly. These are the same redirects that are found in msbuild.exe.config. Unfortunately, this can only be controlled by the exe that is launching the runtime and must be in its config file.

@JoshVarty
Copy link
Contributor Author

Unfortunately, this can only be controlled by the exe that is launching the runtime and must be in its config file.

@mattwar In my use case I'm building Visual Studio extensions and using MSBuildWorkspace to support Visual Studio 2013. Am I correct in understanding that is would mean I'd have to modify deven.exe.config?

Do you see it being possible to compile WPF projects using MSBuildWorkspace in VS 2013?

@Pilchie
Copy link
Member

Pilchie commented May 15, 2015

@JoshVarty Note that you can modify the devenv.exe.config bindings via a pkgdef in your extension if you need to.

@mattwar
Copy link
Contributor

mattwar commented May 15, 2015

@JoshVarty Its not a target scenario for MSBuildWorkspace to be used in VS process.

However, devenv.exe.config already has the redirects for MSBuild (since it uses MSBuild for the project system to load projects too.) But this won't work in VS2013 since those redirects only redirect to MSBuild12, not the newer MsBuild14 that Roslyn is using. You'd still have to update VS2013's config.

It's also not a goal for any Roslyn components in general to be used in VS earlier than 2015.

@mattwar
Copy link
Contributor

mattwar commented May 22, 2015

@JoshVarty it looks like a bug we had not adding a few properties to msbuild is causing this to fail. This has already been fixed for RTM. You can work around the problem by passing these properties into the msbuild workspace.

"DesignTimeBuild" = "true"
"BuildingInsideVisualStudio" = "true"

@JoshVarty
Copy link
Contributor Author

I've tried to verify that these properties are a workaround via:

string path = @"C:\Users\Josh\Documents\Visual Studio 14\Projects\WpfApplication1\WpfApplication1.sln";
var properties = new Dictionary<string, string>() {
    {"CheckForSystemRuntimeDependency", "true" }, //Error occurs with or without this property
    { "DesignTimeBuild", "true" }, 
    { "BuildingInsideVisualStudio", "true" }
};
var msws = MSBuildWorkspace.Create(properties);

var soln = msws.OpenSolutionAsync(path).Result;
var comp = soln.Projects.First().GetCompilationAsync().Result;
var errs = comp.GetDiagnostics().Where(n => n.Severity == DiagnosticSeverity.Error).ToList();

I'm now receiving two (identical) errors:

error CS1703: Multiple assemblies with equivalent identity have been imported: 'Microsoft.Build.Framework.dll' and 'Microsoft.Build.Framework.dll'. Remove one of the duplicate references.

Should the workaround work with RC?

Edit: I should mention I'm testing this code as a ConsoleApplication.

@Pilchie
Copy link
Member

Pilchie commented May 24, 2015

And does this happen with any solution you try to open?

@JoshVarty
Copy link
Contributor Author

A couple things here:

  • No this doesn't happen with any solution I open. I actually can only repro it on a brand new WPF project. If I open an older solution with a mix of projects (one XAML, some Class Libraries) I can't reproduce the error.
  • I just tested the workaround in a VSPackage and I did not receive any errors. (No errors on either brand new WPF project or the mixed project).
  • The debugger actually encounters the same error when showing tooltips:
    image

@mattwar
Copy link
Contributor

mattwar commented May 24, 2015

Do you have the redirects in your config file for the MSBuild dlls?

@mattwar
Copy link
Contributor

mattwar commented May 27, 2015

@JoshVarty Do you have any new information?

@JoshVarty
Copy link
Contributor Author

Sorry, I didn't have the binding redirects. I'm going to test with them later today and let you know.

@JoshVarty
Copy link
Contributor Author

(Disclaimer: I've never really worked with binding redirects before, so let me know if I'm doing anything wrong)

@mattwar I've added the following to my app.config and double-checked that my *.exe.config also contains it. (I'm testing using a ConsoleApplication)

<runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Microsoft.Build"
                              publicKeyToken="b03f5f7f11d5083a"
                              culture="neutral" />
            <bindingRedirect oldVersion="2.0.0.0-12.0.0.0"
                             newVersion="14.0.0.0"/>
            <assemblyIdentity name="Microsoft.Build.Framework"
                              publicKeyToken="b03f5f7f11d5083a"
                              culture="neutral" />
            <bindingRedirect oldVersion="2.0.0.0-12.0.0.0"
                             newVersion="14.0.0.0"/>
            <assemblyIdentity name="Microsoft.Build.Engine"
                              publicKeyToken="b03f5f7f11d5083a"
                              culture="neutral" />
            <bindingRedirect oldVersion="2.0.0.0-12.0.0.0"
                             newVersion="14.0.0.0"/>
         </dependentAssembly>
      </assemblyBinding>
    </runtime>

Even with the binding redirect, I still get error CS1703 complaining about multiple identical assemblies.

@Pilchie As VS2015 works with XAML files now, I'm going to try to get VS2013 working as well. (I know this isn't supported, so I'm fine if you guys tell me I gotta figure it out on my own 😁 )

When I manually edit devenv.exe.config for VS2013 and redirect to version 14.0.0.0 everything works correctly. (I understand that my users will have to manually install the VS2015 build tools). However, I can't seem to get it working via pkgdef.

We've never used pkgdef before. Am I correct in assuming it's an auto-generated file and we interact with it via assembly attributes? We tried adding the following ProvideBindingRedirectionAttribute:

[assembly: ProvideBindingRedirection(AssemblyName = "Microsoft.Build", NewVersion = "14.0.0.0", OldVersionLowerBound = "2.0.0.0", OldVersionUpperBound = "12.0.0.0")]
[assembly: ProvideBindingRedirection(AssemblyName = "Microsoft.Build.Framework", NewVersion = "14.0.0.0", OldVersionLowerBound = "2.0.0.0", OldVersionUpperBound = "12.0.0.0")]
[assembly: ProvideBindingRedirection(AssemblyName = "Microsoft.Build.Engine", NewVersion = "14.0.0.0", OldVersionLowerBound = "2.0.0.0", OldVersionUpperBound = "12.0.0.0")]

We also tried editing the .pkgdef file manually after building, but didn't seem to have any luck. Am I using this attribute right? I'd like to modify the devenv.exe.config bindings as you mentioned.

@Pilchie
Copy link
Member

Pilchie commented May 29, 2015

Tag @jasonmalinowski who has done more with Pkgdefs than me. A hunch though is that the Pkgdefs approach only adds entries, and doesn't work if devenv.exe.config already has them, which VS2013 does :(

@jasonmalinowski
Copy link
Member

I can't recommend the pkgdef approach. The VS binding redirect merger does have some logic to deal with more than one redirect, but given that the project systems themselves have to interact with MSBuild you're putting the product in a very unsupported state.

As much as it pains me to say this, have you tried some sort of AppDomain approach? There you can control your own binding redirects independent of the VS ones which should be a lot more stable. @mattwar already has an implementation of MSBuild workspace that does precisely this which wasn't going to make 1.0 but is in master. You might be better off just making a private build of Roslyn with that.

@mattwar
Copy link
Contributor

mattwar commented May 29, 2015

I've not merge the app domain solution as it has trouble with running unit tests and other memory leaky behavior.

@Pilchie
Copy link
Member

Pilchie commented Jun 11, 2015

@JoshVarty - can you give us a repro project somewhere (emailing me a zip is fine) where you can repro the CS1703 errors? I think that is the only thing still being tracked by this issue, right?

@JoshVarty
Copy link
Contributor Author

Sorry, I just realized the CS1703 errors are introduced by the debugger, but they're masking the two original errors (CS5001 and CS0103 which are still occurring).

I'm going to send you a minimal repro later tonight.

@JoshVarty
Copy link
Contributor Author

Alright I've sent a repro. Let me know if you need anything more.

@mattwar
Copy link
Contributor

mattwar commented Jun 12, 2015

Change your redirects to these and it should work:

        <dependentAssembly>
          <assemblyIdentity name="Microsoft.Build.Engine" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
          <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="14.0.0.0"/>
        </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
          <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="14.0.0.0"/>
        </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity name="Microsoft.Build.Conversion.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
          <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="14.0.0.0"/>
        </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity name="Microsoft.Build.Tasks.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
          <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="14.0.0.0"/>
        </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity name="Microsoft.Build.Utilities.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
          <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="14.0.0.0"/>
        </dependentAssembly>
        <dependentAssembly>
          <assemblyIdentity name="Microsoft.CompactFramework.Build.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
          <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="9.0.0.0"/>
        </dependentAssembly>

@JoshVarty
Copy link
Contributor Author

Just to add to @mattwar's above redirects, one also needs to add the following redirect:

<dependentAssembly>
  <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
  <bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="14.0.0.0"/>
</dependentAssembly>

When I use both this and the above, I can confirm that my errors are no longer present. Thanks to everyone for your help!

@Pilchie
Copy link
Member

Pilchie commented Jun 12, 2015

Thanks for confirming @JoshVarty

@Pilchie
Copy link
Member

Pilchie commented Jun 12, 2015

At this point, I don't think we'll do anything more here at least for 1.0.

@Pilchie Pilchie modified the milestones: Unknown, 1.0 (stable) Jun 12, 2015
@JoshVarty
Copy link
Contributor Author

I should also note that when I use the above binding redirects I no longer receive the debugger errors within Visual Studio and the debugger works as expected.

(I introduced an error into the WPF project, placed a breakpoint, inspected the error and confirmed that I did not see any CS1703 errors: Instead I was shown the correct CS1519 error:http://i.imgur.com/UPhW35K.png)

I suspect I introduced the CS1703 errors when I provided only partial binding redirects. (Though I don't know nearly enough about MSBuild to confirm this)

I think everything is likely taken care of here and we can close this issue.

@Pilchie
Copy link
Member

Pilchie commented Jun 12, 2015

Let's actually close this. I think we're giving up on the idea of doing the AppDomain thing automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE Feature Request Resolution-Won't Fix A real bug, but Triage feels that the issue is not impactful enough to spend time on. Verification Not Required
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants