{"id":37337,"date":"2021-11-11T08:00:20","date_gmt":"2021-11-11T15:00:20","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=37337"},"modified":"2021-11-11T14:47:03","modified_gmt":"2021-11-11T21:47:03","slug":"msbuild-and-64-bit-visual-studio-2022","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/msbuild-and-64-bit-visual-studio-2022\/","title":{"rendered":"MSBuild and 64-bit Visual Studio 2022"},"content":{"rendered":"<p>Visual Studio\u2019s <a href=\"https:\/\/devblogs.microsoft.com\/visualstudio\/visual-studio-2022\/#visual-studio-2022-is-64-bit\">shift to 64-bit<\/a> means your builds in Visual Studio 2022 will run in a 64-bit MSBuild. This will not cause any problems for most people. However, if your build includes a task that is 32-bit only and does not correctly mark itself as a 32-bit task, your build may fail.<\/p>\n<p>The best way to know if this will affect you is by testing your build with a 64-bit version of MSBuild. Visual Studio and Build Tools have included 64-bit MSBuild since Visual Studio 2013, so you can do this in your current version of Visual Studio, as well as with the Visual Studio 2022 previews.<\/p>\n<h2>Background and what\u2019s changed<\/h2>\n<p>MSBuild is part of both Visual Studio and the .NET SDK. The changes described here affect only the Visual Studio MSBuild and will not affect builds started through <code>dotnet build<\/code>.<\/p>\n<p>MSBuild has both 32- and 64-bit executables. Both are installed in every copy of Visual Studio and Visual Studio Build Tools, and scripts that call <code>msbuild.exe<\/code> by full path can select which to use. The Developer Command Prompt for Visual Studio also sets <code>PATH<\/code> to include the MSBuild bin folder.<\/p>\n<p>Visual Studio 2019 is the last version of Visual studio that used the 32-bit version of MSBuild for builds within Visual Studio. Since Visual Studio 2022 is now 64-bit and runs MSBuild in-process, it now runs a 64-bit version of MSBuild, including when you hit F5 or Ctrl-F5. Consistent with the change to 64-bit, the Visual Studio Developer Command Prompt now points to the 64-bit version of MSBuild in the <code>PATH<\/code> (the 32-bit version was on the <code>PATH<\/code> in earlier releases).<\/p>\n<p>The 32-bit MSBuild is run by default in the Azure Pipelines <a href=\"https:\/\/docs.microsoft.com\/azure\/devops\/pipelines\/tasks\/build\/visual-studio-build?view=azure-devops\">Visual Studio Build<\/a> and <a href=\"https:\/\/docs.microsoft.com\/azure\/devops\/pipelines\/tasks\/build\/msbuild?view=azure-devops\">MSBuild<\/a> tasks. To change this, specify <code>msbuildArchitecture: 'x64'<\/code> in your YAML job definition. For GitHub Actions, the <a href=\"https:\/\/github.com\/marketplace\/actions\/setup-msbuild\">setup-msbuild action<\/a> allows for specifying this same setting using <code>msbuild-architecture: 'x64'<\/code>.<\/p>\n<h2>How does this affect my build?<\/h2>\n<p>Changes in Windows between environments may cause problems, if part of your build has a dependency on the 32-bit <a href=\"https:\/\/docs.microsoft.com\/windows\/win32\/winprog64\/file-system-redirector\">filesystem<\/a> or <a href=\"https:\/\/docs.microsoft.com\/windows\/win32\/winprog64\/registry-redirector\">registry<\/a> redirection.<\/p>\n<p>Most MSBuild tasks build for <code>AnyCPU<\/code> and should not have a problem running in a 64-bit environment. Many tasks invoke tools via the command line (they \u201cshell out\u201d) and to those tools it will make no difference whether the task is 32- or 64-bit since the tool continues to run in its own process.<\/p>\n<p>Some tasks p\/invoke into native libraries and thus are sensitive to the architecture they run in.<\/p>\n<p>If you maintain a task, you do not have to rewrite it to run in a 64-bit environment. Instead, you can mark it so that MSBuild runs it in a process with the correct bitness: the 64-bit version of MSBuild can start 32-bit tasks out of process, as the 32-bit version can start 64-bit tasks. See \u201cGuidance for Task Owners\u201d below.<\/p>\n<p>Don\u2019t feel alone if you encounter this\u2014even the <a href=\"https:\/\/docs.microsoft.com\/visualstudio\/extensibility\/visual-studio-sdk\">Visual Studio SDK<\/a> had issues with 64-bit MSBuild compatibility. Some of its tasks are thin wrappers over libraries written in C++ and built for 32-bit x86. We discovered this early in the Visual Studio 2022 lifecycle and the Visual Studio SDK has been updated to support 64-bit MSBuild using the techniques described below since <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.VSSDK.BuildTools\/16.8.1015\">Microsoft.VSSDK.BuildTools 16.8.1015<\/a>.<\/p>\n<h2>Potential issues with MSBuild tasks<\/h2>\n<p>MSBuild tasks are .NET assemblies that add extra functionality to MSBuild. You use them in your normal build, even if you have never written one. MSBuild tasks normally run inside the parent MSBuild process.<\/p>\n<p>If a task is not compatible with 64-bit MSBuild, the task may not be found or it may throw an error. Contact the task owner (such as by filing an issue in their repo), possibly referencing this breaking change blog post. If <em>you<\/em> are the task owner, see \u201cGuidance for task owners\u201d below.<\/p>\n<p>Tasks incompatible with 64-bit MSBuild may fail in a variety of ways; the most common are <a href=\"https:\/\/docs.microsoft.com\/visualstudio\/msbuild\/errors\/msb4018\">MSB4018<\/a> with a <code>System.DllNotFoundException<\/code> and <a href=\"https:\/\/docs.microsoft.com\/visualstudio\/msbuild\/errors\/msb4062\">MSB4062<\/a> \u201ctask could not be loaded\u201d errors.<\/p>\n<h2>Guidance for task (NuGet package) owners<\/h2>\n<p>You have the option of <strong>rewriting your task to support running in a 32- or 64-bit environment<\/strong> and deploying both copies of native assemblies, but this is often difficult, so you may prefer to <strong>configure MSBuild to run your task in a 32-bit process<\/strong> (even from a 64-bit build).<\/p>\n<p>Because this requires starting a new process and communicating with it, it takes more time during the build than running a task in the existing MSBuild process. This is usually not a problem unless the task is called many, many times in your build.<\/p>\n<p>Tasks are made available for use with <a href=\"https:\/\/docs.microsoft.com\/visualstudio\/msbuild\/usingtask-element-msbuild\"><code>UsingTask<\/code><\/a> elements. You can <a href=\"https:\/\/docs.microsoft.com\/visualstudio\/msbuild\/how-to-configure-targets-and-tasks#usingtask-attributes-and-task-parameters\">configure the task<\/a> to indicate that it requires a specific runtime environment by specifying the <code>Architecture<\/code> attribute in the <code>UsingTask<\/code> element.<\/p>\n<p>A well-specified <code>UsingTask<\/code> for a 32-bit-only assembly looks something like this:<\/p>\n<pre><code class=\"language-xml\">&lt;UsingTask TaskName=\"TaskThatNeedsX86Library\"\r\n           AssemblyFile=\"$(MSBuildThisFileDirectory)ArchSpecificTasks.dll\"\r\n           Architecture=\"x86\" \/&gt;<\/code><\/pre>\n<p>This change is <strong>backward compatible<\/strong> since MSBuild has supported running tasks in a different architecture since .NET 4.5 and Visual Studio 2012. Specifying <code>Architecture<\/code> will not change how the task runs in a 32-bit MSBuild environment, but will cause 64-bit MSBuild to run it in a secondary 32-bit process. Because of this, we recommend making this change unconditionally and not trying to detect Visual Studio 2022 (MSBuild 17) specifically.<\/p>\n<h3>Testing<\/h3>\n<p>We recommend testing your task in a few build scenarios to make sure your changes are working:<\/p>\n<ol>\n<li>UI-driven builds in Visual Studio 2019 (to ensure that there hasn\u2019t been a regression in that scenario).<\/li>\n<li>Command-line builds using 32-bit <code>MSBuild.exe<\/code> from Visual Studio 2019 (MSBuild 16).<\/li>\n<li>Command-line builds using 64-bit <code>MSBuild.exe<\/code> from Visual Studio 2019 (MSBuild 16).<\/li>\n<li>UI-driven builds in the latest Visual Studio 2022 (this is a primary developer scenario going forward).<\/li>\n<li>Command-line builds using 64-bit <code>MSBuild.exe<\/code> from Visual Studio 2022 (MSBuild 17).<\/li>\n<li>Command-line builds using the .NET SDK (if your task supports this environment). These use <code>dotnet build<\/code> and should be unaffected by your changes.<\/li>\n<\/ol>\n<h3>Known issues<\/h3>\n<p>If a task is defined in a .NET assembly compiled as 32-bit only, MSBuild will fail to load it with an error like<\/p>\n<pre><code class=\"language-text\">S:\\BitnessInMSBuild\\ShowErrors.proj(13,5): error MSB4062: The \"TaskCompiledForx86\" task could not be loaded from the assembly S:\\BitnessInMSBuild\\TaskCompiledForx86\\bin\\Debug\\net472\\TaskCompiledForx86.dll. Could not load file or assembly 'file:\/\/\/S:BitnessInMSBuildTaskCompiledForx86binDebugnet472TaskCompiledForx86.dll' or one of its dependencies. An attempt was made to load a program with an incorrect format. Confirm that the &lt;UsingTask&gt; declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.<\/code><\/pre>\n<p><em>even if the <code>UsingTask<\/code> correctly declares an <code>Architecture<\/code><\/em>. This is tracked by <a href=\"https:\/\/github.com\/dotnet\/msbuild\/issues\/6461\">dotnet\/msbuild#6461<\/a>.<\/p>\n<p>You can work around this issue by recompiling your task assembly as AnyCPU and additionally specifying the <code>Architecture<\/code>. In that case, the MSBuild engine can <em>load<\/em> the task in a 64-bit environment but it will only <em>execute<\/em> it in a 32-bit process.<\/p>\n<h2>Mitigation for users of tasks that they don\u2019t own<\/h2>\n<p>Unfortunately, it is difficult to work around task misconfiguration if you do not control the <code>UsingTask<\/code>. <a href=\"https:\/\/github.com\/dotnet\/msbuild\/issues\/5541\">dotnet\/msbuild#5541<\/a> tracks a change that would make it easier to override an incorrect <code>UsingTask<\/code> in your project. Please let us know if this would be useful to you in a future Visual Studio\/MSBuild release.<\/p>\n<h2>Next Steps<\/h2>\n<p>The upgrade to Visual Studio 2022 is an exciting one. 64-bit MSBuild is just one of the new features we&#8217;ve prepared for you and we&#8217;re excited for you to try them out. When you do, be sure to leave your feedback below, we&#8217;d love to hear about your experiences with the upgrade and with 64-Bit MSBuild overall!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how the shift to 64-bit Visual Studio can impact your builds<\/p>\n","protected":false},"author":7038,"featured_media":37338,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,646],"tags":[],"class_list":["post-37337","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-visual-studio"],"acf":[],"blog_post_summary":"<p>Learn how the shift to 64-bit Visual Studio can impact your builds<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/37337","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/7038"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=37337"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/37337\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/37338"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=37337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=37337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=37337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}