-
Notifications
You must be signed in to change notification settings - Fork 89
Make the MSBuild runtime assembly check more correct #360
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
…code + link to enable searching
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| # MSBL001 - MSBuild runtime package is referenced without Runtime Assets excluded | ||
|
|
||
| ## Error Message | ||
|
|
||
| > A PackageReference to the package '{PackageId}' at version '{Version}' is present in this project without ExcludeAssets="runtime" set. This can cause errors at run-time due to MSBuild assembly-loading. | ||
|
|
||
| ## Cause | ||
|
|
||
| This error occurs when your project references MSBuild NuGet packages (such as `Microsoft.Build`, `Microsoft.Build.Framework`, `Microsoft.Build.Utilities.Core`, etc.) without excluding their runtime assets. When you use Microsoft.Build.Locator, you want MSBuildLocator to load MSBuild assemblies from an installed Visual Studio or .NET SDK instance, not from the NuGet packages in your output directory. | ||
|
|
||
| ## Why This Is a Problem | ||
|
|
||
| When MSBuild runtime assemblies are copied to your application's output directory, your application may load these assemblies instead of the MSBuild installation that MSBuildLocator registered. This can lead to several runtime issues: | ||
|
|
||
| 1. **Assembly version conflicts**: Your application loads MSBuild assemblies from your output directory while MSBuildLocator tries to load from a different MSBuild installation | ||
| 2. **Missing SDKs and build logic**: The MSBuild assemblies in your output directory don't include the SDKs, targets, and build logic needed to build real projects | ||
| 3. **Inconsistent behavior**: Your application may behave differently than `MSBuild.exe`, `dotnet build`, or Visual Studio when evaluating projects | ||
|
|
||
| ## Example Runtime Error | ||
|
|
||
| Without `ExcludeAssets="runtime"`, you may encounter errors like: | ||
|
|
||
| ``` | ||
| System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Build, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. | ||
| ``` | ||
|
|
||
| Or: | ||
|
|
||
| ``` | ||
| System.InvalidOperationException: SDK 'Microsoft.NET.Sdk' could not be resolved. The SDK resolver "Microsoft.DotNet.MSBuildSdkResolver" returned null. | ||
| ``` | ||
|
|
||
| This happens because your application loads MSBuild assemblies from your bin folder (e.g., version 15.5.180) while MSBuildLocator has registered a different MSBuild installation (e.g., version 17.0) to use at runtime. The .NET runtime gets confused about which assemblies to use, leading to version conflicts and missing dependencies. | ||
|
|
||
| ## Solution | ||
|
|
||
| Add `ExcludeAssets="runtime"` to all MSBuild PackageReferences in your project file: | ||
|
|
||
| ```xml | ||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.Build" ExcludeAssets="runtime" /> | ||
| <PackageReference Include="Microsoft.Build.Framework" ExcludeAssets="runtime" /> | ||
| <PackageReference Include="Microsoft.Build.Utilities.Core" ExcludeAssets="runtime" /> | ||
| ... | ||
| </ItemGroup> | ||
| ``` | ||
|
|
||
| This tells NuGet to use these packages only for compilation, not at runtime. At runtime, MSBuildLocator will load MSBuild assemblies from the registered Visual Studio or .NET SDK installation. | ||
|
|
||
| ## Alternative: Disable the Check (Not Recommended) | ||
|
|
||
| If you need to distribute MSBuild assemblies with your application (not recommended), you can disable this check by setting the following property in your project file: | ||
|
|
||
| ```xml | ||
| <PropertyGroup> | ||
| <DisableMSBuildAssemblyCopyCheck>true</DisableMSBuildAssemblyCopyCheck> | ||
| </PropertyGroup> | ||
| ``` | ||
|
|
||
| **Warning**: Disabling this check means you must distribute all of MSBuild and its associated toolset with your application, which is generally not recommended. The MSBuild team does not support this scenario, and you may encounter issues with SDK resolution and build logic. | ||
|
|
||
| ## Related Documentation | ||
|
|
||
| - [Use Microsoft.Build.Locator](https://learn.microsoft.com/visualstudio/msbuild/updating-an-existing-application#use-microsoftbuildlocator) | ||
| - [MSBuildLocator on GitHub](https://github.com/microsoft/MSBuildLocator) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,11 +14,12 @@ | |
| <_MSBuildAssembliesCopyLocalItems Include="@(RuntimeCopyLocalItems->WithMetadataValue('NuGetPackageId', 'NuGet.Frameworks'))" /> | ||
| <MSBuildAssembliesCopyLocalItems Include="@(_MSBuildAssembliesCopyLocalItems->WithMetadataValue('CopyLocal', 'true')->WithMetadataValue('AssetType', 'runtime'))" /> | ||
| <_DistinctMSBuildPackagesReferencedPoorly Include="@(MSBuildAssembliesCopyLocalItems->Metadata('NuGetPackageId')->Distinct())" /> | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. such assets will have the nuget package id and version metadata on them, so we can distinct the IDs easily and make nice error messages. |
||
| <_DistinctPackagesWithVersions Include="@(_DistinctMSBuildPackagesReferencedPoorly->'%(NuGetPackageId)@%(NuGetPackageVersion)')" /> | ||
| </ItemGroup> | ||
|
|
||
| <Error | ||
|
Check failure on line 19 in src/MSBuildLocator/build/Microsoft.Build.Locator.targets
|
||
| Condition="@(_DistinctPackagesWithVersions->Count()) > 0" | ||
| Text="A PackageReference to an MSBuild run-time package without ExcludeAssets="runtime" exists in your project. This will cause MSBuild run-time assemblies to be copied to your output directory, causing your application to load them at runtime. To use the copy of MSBuild registered by MSBuildLocator, set ExcludeAssets="runtime" on the MSBuild PackageReferences. To disable this check, set the property DisableMSBuildAssemblyCopyCheck=true in your project file (not recommended as you must distributed all of MSBuild + associated toolset). Package(s) referenced: @(_DistinctPackagesWithVersions, ', ')" /> | ||
| Code="MSBL001" | ||
| Text="A PackageReference to the package '%(_DistinctMSBuildPackagesReferencedPoorly.NuGetPackageId)' at version '%(_DistinctMSBuildPackagesReferencedPoorly.NuGetPackageVersion)' is present in this project without ExcludeAssets="runtime" set. This can cause errors at run-time due to MSBuild assembly-loading." | ||
| HelpLink="https://aka.ms/msbuild/locator/diagnostics/MSBL001" | ||
| /> | ||
| </Target> | ||
| </Project> | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once we have the candidate set, we can find just the ones that are runtime assets and were copylocal'd.