MSBuild and 64-bit Visual Studio 2022
Visual Studio’s shift to 64-bit 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.
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.
Background and what’s changed
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
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
msbuild.exe by full path can select which to use. The Developer Command Prompt for Visual Studio also sets
PATH to include the MSBuild bin folder.
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
PATH (the 32-bit version was on the
PATH in earlier releases).
The 32-bit MSBuild is run by default in the Azure Pipelines Visual Studio Build and MSBuild tasks. To change this, specify
msbuildArchitecture: 'x64' in your YAML job definition. For GitHub Actions, the setup-msbuild action allows for specifying this same setting using
How does this affect my build?
Changes in Windows between environments may cause problems, if part of your build has a dependency on the 32-bit filesystem or registry redirection.
Most MSBuild tasks build for
AnyCPU and should not have a problem running in a 64-bit environment. Many tasks invoke tools via the command line (they “shell out”) 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.
Some tasks p/invoke into native libraries and thus are sensitive to the architecture they run in.
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 “Guidance for Task Owners” below.
Don’t feel alone if you encounter this—even the Visual Studio SDK 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 Microsoft.VSSDK.BuildTools 16.8.1015.
Potential issues with MSBuild tasks
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.
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 you are the task owner, see “Guidance for task owners” below.
Tasks incompatible with 64-bit MSBuild may fail in a variety of ways; the most common are MSB4018 with a
System.DllNotFoundException and MSB4062 “task could not be loaded” errors.
Guidance for task (NuGet package) owners
You have the option of rewriting your task to support running in a 32- or 64-bit environment and deploying both copies of native assemblies, but this is often difficult, so you may prefer to configure MSBuild to run your task in a 32-bit process (even from a 64-bit build).
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.
Tasks are made available for use with
UsingTask elements. You can configure the task to indicate that it requires a specific runtime environment by specifying the
Architecture attribute in the
UsingTask for a 32-bit-only assembly looks something like this:
<UsingTask TaskName="TaskThatNeedsX86Library" AssemblyFile="$(MSBuildThisFileDirectory)ArchSpecificTasks.dll" Architecture="x86" />
This change is backward compatible since MSBuild has supported running tasks in a different architecture since .NET 4.5 and Visual Studio 2012. Specifying
Architecture 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.
We recommend testing your task in a few build scenarios to make sure your changes are working:
- UI-driven builds in Visual Studio 2019 (to ensure that there hasn’t been a regression in that scenario).
- Command-line builds using 32-bit
MSBuild.exefrom Visual Studio 2019 (MSBuild 16).
- Command-line builds using 64-bit
MSBuild.exefrom Visual Studio 2019 (MSBuild 16).
- UI-driven builds in the latest Visual Studio 2022 (this is a primary developer scenario going forward).
- Command-line builds using 64-bit
MSBuild.exefrom Visual Studio 2022 (MSBuild 17).
- Command-line builds using the .NET SDK (if your task supports this environment). These use
dotnet buildand should be unaffected by your changes.
If a task is defined in a .NET assembly compiled as 32-bit only, MSBuild will fail to load it with an error like
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 <UsingTask> 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.
even if the
UsingTask correctly declares an
Architecture. This is tracked by dotnet/msbuild#6461.
You can work around this issue by recompiling your task assembly as AnyCPU and additionally specifying the
Architecture. In that case, the MSBuild engine can load the task in a 64-bit environment but it will only execute it in a 32-bit process.
Mitigation for users of tasks that they don’t own
Unfortunately, it is difficult to work around task misconfiguration if you do not control the
UsingTask. dotnet/msbuild#5541 tracks a change that would make it easier to override an incorrect
UsingTask in your project. Please let us know if this would be useful to you in a future Visual Studio/MSBuild release.
The upgrade to Visual Studio 2022 is an exciting one. 64-bit MSBuild is just one of the new features we’ve prepared for you and we’re excited for you to try them out. When you do, be sure to leave your feedback below, we’d love to hear about your experiences with the upgrade and with 64-Bit MSBuild overall!
Could it explain that this warning would appear on x86 builds in VS2022, when there was no warning in VS2019?
ALINK : warning AL1073: Referenced assembly ‘mscorlib.dll’ targets a different processor
It looks like a revert situation of https://developercommunity.visualstudio.com/t/alink-still-generates-warning-when-compiling-assem/95054
I hope I can set up a minimal repro, but I got this in two different projects so far, involving .net framework and c++/cli projects.
Hey! This looks similar to an msbuild bug that should have been fixed. Could you file a feedback ticket at Developer Community and include a binlog of your build? Also any relevant info (platform that’s being built, minimal project if possible, etc.)
When you create the issue, mention this blog post or come back to this post and ping us. That should speed up routing it to the right place!
Hi Ben! Thanks for your answer, here is the feedback ticket I filed regarding this bug: https://developercommunity.visualstudio.com/t/Warning-AL1073-when-compiling-x86-NET-F/1582168?space=8
Thanks! I’ve replied to the feedback ticket.
I feel like this is a dumb and easy to solve issue, but I can’t find a clear answer. I have a build that fails because the project references a Windows SDK, which by default gets installed to “C:\Program Files (x86)\Windows Kits” but the reference in the csproj is to “$(ProgramFiles)\Windows Kits\10\UnionMetadata\10.0.18362.0\Windows.winmd”.
On 32bit this works fine because $(ProgramFiles) resolves to “C:\Program Files (x86)” but on 64bit it resolves to good ol’ “C:\Program Files\” which doesn’t have the Windows Kits folder.
I could presumably hardcode $(ProgramFiles) to be C:\Program Files (x86) but that doesn’t work for all machines. I feel like all I want is something like $(ProgramFiles32) or something but I can’t find a variable that exists.
What is the “correct” way to resolve this so that it can build successfully on both 32bit and 64bit MSBuild?
Does referencing https://www.nuget.org/packages/Microsoft.Windows.SDK.Contracts/ rather than something local resolve the issue?
$(MSBuildProgramFiles32), see MSBuild reserved and well-known properties
Isn’t MSBuild written on C#? If not, WHY NOT? If yes, why ON VIRTUAL MACHINE we still have headache with damn 32/64 bits?? Isn’t it PRIMARY GOAL of the virtual machine to LEAVE BEHIND all hardware mess with bits, big/little endian, etc??
Why MS still have issues with 32/64 after 20 years sitting in virtual machine .NET?
MSBuild is in C# and AnyCPU, but this does not help for this problem. Architecture problem occurs when there’s any native code loaded into the process. The executable file can be AnyCPU, but a process at a single time has one architecture.
I try to use ACCORD.NET Video and DirectShow with VS 2022 Community and .NET 6
This worked fine under VS 2019 and .NET 5.0.
Can that be fixed.
I’m not sure exactly what problem you’re seeing here – is the code no longer compiling, or does the code compile but not do what you expect at runtime? In either case, submitting feedback through the Developer Community will help get your question to the most appropriate team the fastest.
This is nice, but now I can’t build my solutions which contain projects with x86 STA COM references. Only x86 msbuild can build these – is there an option to instruct VS 2022 to use the 32bit msbuild on these projects?