diff --git a/docs/core/compatibility/10.0.md b/docs/core/compatibility/10.0.md index 07d6f374888e2..1db9ccf2bcb2b 100644 --- a/docs/core/compatibility/10.0.md +++ b/docs/core/compatibility/10.0.md @@ -111,6 +111,7 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af | [.NET CLI `--interactive` defaults to `true` in user scenarios](sdk/10.0/dotnet-cli-interactive.md) | Behavioral change | Preview 3 | | [`dotnet` CLI commands log non-command-relevant data to stderr](sdk/10.0/dotnet-cli-stderr-output.md) | Behavioral change | RC 2 | | [.NET tool packaging creates RuntimeIdentifier-specific tool packages](sdk/10.0/dotnet-tool-pack-publish.md) | Behavioral change | Preview 6 | +| [Code coverage EnableDynamicNativeInstrumentation defaults to false](sdk/10.0/code-coverage-dynamic-native-instrumentation.md) | Behavioral change | GA | | [Default workload configuration from 'loose manifests' to 'workload sets' mode](sdk/10.0/default-workload-config.md) | Behavioral change | Preview 2 | | [dnx.ps1 file is no longer included in .NET SDK](sdk/10.0/dnx-ps1-removed.md) | Source incompatible | GA | | [`dotnet new sln` defaults to SLNX file format](sdk/10.0/dotnet-new-sln-slnx-default.md) | Behavioral change | RC 1 | diff --git a/docs/core/compatibility/sdk/10.0/code-coverage-dynamic-native-instrumentation.md b/docs/core/compatibility/sdk/10.0/code-coverage-dynamic-native-instrumentation.md new file mode 100644 index 0000000000000..42357703a88c5 --- /dev/null +++ b/docs/core/compatibility/sdk/10.0/code-coverage-dynamic-native-instrumentation.md @@ -0,0 +1,66 @@ +--- +title: "Breaking change - Code coverage EnableDynamicNativeInstrumentation defaults to false" +description: "Learn about the breaking change in .NET 10 where dynamic native instrumentation is disabled by default when collecting code coverage." +ms.date: 11/05/2025 +ai-usage: ai-assisted +ms.custom: https://github.com/dotnet/docs/issues/49376 +--- + +# Code coverage EnableDynamicNativeInstrumentation defaults to false + +Running `dotnet test --collect:"Code Coverage"` now disables dynamic native instrumentation by default. This change affects how code coverage is collected from native code. It doesn't affect how code coverage is collected from managed code. + +## Version introduced + +.NET 10 GA + +## Previous behavior + +Previously, dynamic native instrumentation was enabled by default and used a fallback for native modules when static native instrumentation couldn't be used. This behavior is described in [Static and dynamic native instrumentation](/visualstudio/test/customizing-code-coverage-analysis?view=vs-2022#static-and-dynamic-native-instrumentation). + +```bash +dotnet test --collect:"Code Coverage" +# Dynamic native instrumentation was enabled by default +``` + +## New behavior + +Starting in .NET 10, dynamic native instrumentation is disabled by default. The `false` option is set by default from `dotnet test` and `vstest`. If you explicitly set the option in a *runsettings* file, it isn't overridden. + +```bash +dotnet test --collect:"Code Coverage" +# Dynamic native instrumentation is now disabled by default +``` + +You can re-enable dynamic native instrumentation by setting `true` in your *runsettings* file. However, when you do so, it might fail with "The code execution cannot proceed because covrun64.dll was not found." This error can also happen for `covrun32.dll` in a 32-bit process. + +## Type of breaking change + +This change is a [behavioral change](../../categories.md#behavioral-change). + +## Reason for change + +Dynamic native instrumentation was enabled by default to maintain backwards compatibility in `dotnet test`. However, its way of injecting DLLs into the process isn't standard. With [security hardening changes](https://github.com/dotnet/runtime/pull/112359) in the .NET 10 runtime, it fails to find the linked DLL, causing the process to [crash with error](https://github.com/dotnet/sdk/issues/50950). The error might not be visible in non-interactive sessions or in the command line, but the process does crash. + +Dynamic native instrumentation is already disabled by default by `dotnet-coverage`, which is an alternative way to collect code coverage using the same underlying tools. It's also disabled by default for solutions in Visual Studio that don't have native projects. + +## Recommended action + +If you collect coverage on solutions that don't have any native components, you shouldn't be affected. However, you might observe increased performance when collecting coverage. + +If you collect coverage on solutions that include native components, such as C++ projects, you have the following options: + +- Configure your projects to use [static native instrumentation](/visualstudio/test/customizing-code-coverage-analysis#static-and-dynamic-native-instrumentation) + + OR + +- Update to Microsoft.CodeCoverage 18.0.1 and enable dynamic native instrumentation: + + - Add the setting `true` to your *runsettings* file. + - Globally opt out from this new default by setting the `VSTEST_DISABLE_DYNAMICNATIVE_CODECOVERAGE_DEFAULT_SETTING=1` environment variable. + + Similarly, when collecting code coverage with `vstest.console`, VSTest version 18.0.1 and newer is required to successfully collect dynamic native coverage on systems that have the .NET 10 SDK installed. + +## Affected APIs + +None. diff --git a/docs/core/compatibility/toc.yml b/docs/core/compatibility/toc.yml index 084502fd419de..a2c6899095893 100644 --- a/docs/core/compatibility/toc.yml +++ b/docs/core/compatibility/toc.yml @@ -122,6 +122,8 @@ items: href: reflection/10/makegeneric-signaturetype-validation.md - name: SDK and MSBuild items: + - name: Code coverage EnableDynamicNativeInstrumentation defaults to false + href: sdk/10.0/code-coverage-dynamic-native-instrumentation.md - name: .NET CLI `--interactive` defaults to `true` in user scenarios href: sdk/10.0/dotnet-cli-interactive.md - name: "`dotnet` CLI commands log non-command-relevant data to stderr"