TQ
dev.com

Blog about software development

Subscribe

Visual Studio's MSBuild vs. dotnet build

23 Feb 2022 - by 'Maurits van der Schee'

Visual Studio Community 2022 is a very advanced IDE that has very good support for Visual Basic and the cross platform .NET 5. A C# programmer can choose to use Visual Studio Code, but that has no (language) support for Visual Basic. And since I was working on a Visual Basic application I was using Visual Studio Community as an IDE. This post explains the incompatibility between .NET 5 and a custom "Build Task" in Visual Studio Community's build tool "MSBuild" (also applies to Visual Studio Professional).

What is MSBuild?

The first problem is that you may not even know that you are using "MSBuild" and not "dotnet build" in Visual Studio. I expected Visual Studio Community to use "dotnet build" to build .NET 5 projects, like it does in Visual Studio Code and wasn't even aware of these two different build tools that Microsoft has.

Incompatible build tasks

I'm using a custom build task to generate view code. This code is written for .NET 5 and my project is .NET 5 as well. It turns out that "dotnet build" has no problem executing this build task.

<UsingTask
   TaskName="GenerateViews"
   AssemblyFile="tools\Maussoft.Mvc.ViewGen.dll"
/>

<Target Name="BeforeBeforeBuild" BeforeTargets="BeforeBuild">
  <GenerateViews />
</Target>

MSBuild on the other hand can only run .Net 4.8 tasks and therefor this pure .NET 5 application in the latest Visual Studio, requires me to recompile my task (view generator) for .NET 4.8. This is very odd and unexpected in my opinion. Also I feel this is not very well documented.

Workaround: Condition "MSBuildRuntimeType"

Instead of modifying the project file you can make the project file compatible with both "MSBuild" and "dotnet build" by using a "Condition" property:

<UsingTask 
  Condition="'$(MSBuildRuntimeType)' != 'Core'"
  TaskName="GenerateViews"
  AssemblyFile="tools\win\Maussoft.Mvc.ViewGen.dll"
/>

<UsingTask
  Condition="'$(MSBuildRuntimeType)' == 'Core'"
  TaskName="GenerateViews"
  AssemblyFile="tools\Maussoft.Mvc.ViewGen.dll"
/>

As you can see I use the "$(MSBuildRuntimeType)" parameter that is not set to 'Core' when building with MSBuild and allows you to differentiate between the .NET 4.8 compiled view generator (for Visual Studio Community) and the cross-platform .NET 5 view generator (for Visual Studio Code).

Conclusion

Once you know that Microsoft didn't upgrade their MSBuild build tool to .NET 5 you understand that it can't run .NET 5 custom tasks. I feel this is unexpected and not well documented and it may cost you a lot of time (as it did for me). I wish I could recommend Visual Basic programmers to switch to the paid "Rider" IDE product (by JetBrains), but it's language support for Visual Basic is disappointing. On the upside: It is cross-platform, has a very good developer experience and allows you to use "dotnet build" instead of "MSBuild" to build .NET 5 projects.


PS: Liked this article? Please share it on Facebook, Twitter or LinkedIn.