NuGet Detection depends on the following to successfully run:
- One or more
*.nuspec,*.nupkg,*.packages.config, or.*csprojfiles. - The files each NuGet detector searches for:
NuGet Detection is performed by parsing any *.nuspec, *.nupkg, *.packages.config, or *.project.assets files found under the scan directory. By searching for all *.nuspec, *.nupkg files on disk the global NuGet cache gets searched which can include packages that are not included in the final build.
The NuGetProjectCentric detector raises NuGet components referenced by projects that use the latest NuGet (v3 or later) and build-integrated PackageReference items. These components represent both direct dependencies and transitive dependencies brought in by references from direct package and project references. Packages that contribute no assets to the project or exclusively contribute Compile assets are treated as development dependencies.
The .NET SDK will perform conflict resolution for all packages during the build. This process will remove assets from packages that overlap with assets of the same name that come from the .NET framework that's used by the project. For example if a project references System.Text.Json version 6.0.0 and targets net8.0 which includes a newer System.Text.Json the .NET SDK will ignore all the assets provided by the System.Text.Json package and only use those provided by the framework. Unfortunately the result of this process is not persisted in any build artifact. To approximate this we capture a list of packages per framework version that would lose to the framework assets. When examining packages referenced by a project for a given framework, if we find that its included in the list we'll mark it as a development dependency.
Future versions of the .NET SDK have moved this framework conflict resolution into NuGet via the PrunePackageReference feature. This feature will apply similar rules to conflict resolution during restore and avoid even downloading the package. As a result the packages will not appear at all in the assets file since they are no longer used.
The NuGetPackagesConfig detector raises NuGet components referenced by projects or solutions that use the older NuGet (v2) packages.config file.
The MSBuildBinaryLog detector is a DefaultOff detector intended to eventually replace both the NuGetProjectCentric and DotNet detectors. It combines MSBuild binary log (binlog) information with project.assets.json to provide enhanced component detection with project-level classifications.
It looks for project.assets.json files and separately discovers *.binlog files. The binlog provides build-time context that isn't available from project.assets.json alone.
The detector extracts the following MSBuild properties from binlog data:
| Property | Usage |
|---|---|
NETCoreSdkVersion |
Registered as the SDK version for the DotNet component. More accurate than dotnet --version, which can differ due to global.json rollforward. |
OutputType |
Classifies projects as "application" (Exe, WinExe, AppContainerExe) or "library" (Library, Module). The DotNet detector uses PE header inspection, which requires compiled output. |
ProjectAssetsFile |
Maps binlog project info to the corresponding project.assets.json on disk. |
TargetFramework / TargetFrameworks |
Identifies inner builds for multi-targeted projects and determines per-TFM properties. |
IsTestProject |
When true, all dependencies of the project are marked as development dependencies. |
IsShipping |
When false, all dependencies are marked as development dependencies. |
IsDevelopment |
When true, all dependencies are marked as development dependencies. |
IsPackable |
Indicates whether the project produces a NuGet package. |
SelfContained |
Detects self-contained deployment. Combined with lock file heuristics. |
PublishAot |
When true, project is treated as self-contained. Typically only set during publish pass. |
The detector reads IsDevelopmentDependency metadata from PackageReference and PackageDownload items in the binlog:
- PackageReference: When
IsDevelopmentDependencyistrue, the package and all of its transitive dependencies are marked as development dependencies. This allows annotating a single top-level dependency to classify its entire closure as dev-only. If a transitive dependency should remain non-dev, reference it directly (or transitively via a non-overridden dependency) so that it is also registered through a non-dev path. - PackageReference: When
IsDevelopmentDependencyisfalse, the package and all of its transitive dependencies are classified using the explicit override rather than the default heuristics. - PackageDownload: Packages are registered as development dependencies by default unless explicitly overridden via
IsDevelopmentDependencymetadata.
For multi-targeted projects, the detector understands the MSBuild outer/inner build structure. Properties from inner builds (per-TFM) are tracked separately, and when a project appears in multiple binlogs (e.g., a build pass and a publish pass), their properties are merged so that values like PublishAot (typically only set during publish) are available when processing the shared project.assets.json.
When no binlog is available for a project, the detector falls back to standard NuGet detection behavior (equivalent to the NuGetProjectCentric detector).
Pass --DetectorArgs MSBuildBinaryLog=EnableIfDefaultOff and ensure a *.binlog file is present in the scan directory (e.g., by building with dotnet build -bl).
- Any components that are only found in
*.nuspecor*.nupkgfiles will not be detected with the latest NuGet Detector approach, because the NuGet detector that scans*.nuspecor*.nupkgfiles overreports. This is due to of NuGet's restore behaviour which downloads all possible dependencies before resolving the final dependency graph.