Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 5, 2025

.NET 10 disables dynamic native instrumentation by default when collecting code coverage via dotnet test --collect:"Code Coverage". The change addresses process crashes caused by security hardening in the .NET 10 runtime that prevents non-standard DLL injection.

Changes

  • Breaking change document: Created docs/core/compatibility/sdk/10.0/code-coverage-dynamic-native-instrumentation.md documenting the behavioral change
  • TOC and index updates: Added entries to toc.yml and 10.0.md in alphabetical order

Impact

Users collecting coverage on solutions without native components are unaffected and may see performance improvements. Users with C++ or other native projects have three mitigation options:

  1. Set VSTEST_DISABLE_DYNAMICNATIVE_CODECOVERAGE_DEFAULT_SETTING=1 environment variable to restore previous behavior
  2. Stay on .NET 9 until the dynamic instrumentation issue is resolved
  3. Temporarily disable code coverage collection

Re-enabling via <EnableDynamicNativeInstrumentation>true</EnableDynamicNativeInstrumentation> in runsettings may fail with "covrun64.dll was not found" errors due to the runtime security changes.

Fixes #50950

Original prompt

This section details on the original issue you should resolve

<issue_title>[Breaking change]: Code coverage EnableDynamicNativeInstrumentation is set to false</issue_title>
<issue_description>### Description

Running dotnet test --collect:"Code Coverage" disables dynamic native instrumentation by default. This change affects how code coverage is collected from native code. It does not affect how code coverage is collected from managed code.

<EnableDynamicNativeInstrumentation>false</EnableDynamicNativeInstrumentation> option is set by default from dotnet test / vstest. If the option was explicitly set by user in runsettings, it will not be overriden.

Version

.NET 10 GA

Previous behavior

Dynamic native instrumentation was enabled by default, and used a fallback for native modules when static native instrumentation could not be used. As described in https://learn.microsoft.com/visualstudio/test/customizing-code-coverage-analysis?view=vs-2022#static-and-dynamic-native-instrumentation

New behavior

Dynamic native instrumentation is disabled by default. When re-enabled, it might fail with "The code execution cannot proceed because covrun64.dlls was not found." This error can also happen for covrun32.dll in 32-bit process.

Type of breaking change

  • Binary incompatible: Existing binaries might encounter a breaking change in behavior, such as failure to load or execute, and if so, require recompilation.
  • Source incompatible: When recompiled using the new SDK or component or to target the new runtime, existing source code might require source changes to compile successfully.
  • Behavioral change: Existing binaries might behave differently at run time.

Reason for change

Dynamic native instrumentation was enabled by default, to keep backwards compatibility in dotnet test, but its way of injecting dlls into the process is not standard, and with security hardening changes in .NET 10 runtime it fails to find the linked dll. Causing process crash, and the following error: dotnet/sdk#50950

The error might not be visible in non-interactive sessions or in command line, but the process crash happens.

The dynamic native instrumentation is already disabled by default by dotnet-coverage, an alternative way to collect code coverage using the same underlying tools. And by default disabled for solutions in Visual Studio that don't have native projects.

Recommended action

Users that collect coverage on solutions that don't have any native components should not be affected. They might observe increased performance of collecting coverage.

Users that collect coverage on solutions that include native component, such as C++ projects and wish to re-enable dynamic native instrumentation should remain on NET9, or disable collecting code coverage until the problem is solved.

Users who wish to globally opt-out from this new default can set VSTEST_DISABLE_DYNAMICNATIVE_CODECOVERAGE_DEFAULT_SETTING=1 environment variable.

Feature area

SDK

Affected APIs

No response


Associated WorkItem - 500372</issue_description>

Comments on the Issue (you are @copilot in this section)

@gewarren @nohwnd Yes it's fine to just edit the description. Imported into Quest means a mirrored Azure DevOps work item has been created, but it will automatically get any updates from here.

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.


Internal previews

📄 File 🔗 Preview link
docs/core/compatibility/10.0.md Breaking changes in .NET 10
docs/core/compatibility/sdk/10.0/code-coverage-dynamic-native-instrumentation.md Code coverage EnableDynamicNativeInstrumentation defaults to false
docs/core/compatibility/toc.yml docs/core/compatibility/toc

…veInstrumentation

Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com>
Co-authored-by: gewarren <24882762+gewarren@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix code coverage dynamic native instrumentation setting Document breaking change: Code coverage EnableDynamicNativeInstrumentation defaults to false in .NET 10 Nov 5, 2025
Copilot AI requested a review from gewarren November 5, 2025 01:50
Copilot finished work on behalf of gewarren November 5, 2025 01:50
@gewarren gewarren marked this pull request as ready for review November 5, 2025 02:22
@gewarren gewarren requested a review from a team as a code owner November 5, 2025 02:22
@gewarren gewarren requested review from Copilot and nohwnd November 5, 2025 02:22
@gewarren
Copy link
Contributor

gewarren commented Nov 5, 2025

@nohwnd I know you said there were some updates to make. Can you add them as suggestions in this PR?

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds documentation for a breaking change in .NET 10 where code coverage dynamic native instrumentation is now disabled by default. The change addresses a crash issue caused by security hardening in the runtime.

  • Adds a new breaking change article documenting the default behavior change for EnableDynamicNativeInstrumentation
  • Updates the table of contents to include the new article in the SDK section
  • Updates the 10.0.md master list to include the breaking change entry

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
docs/core/compatibility/sdk/10.0/code-coverage-dynamic-native-instrumentation.md New breaking change article documenting the default change from enabled to disabled for dynamic native instrumentation
docs/core/compatibility/toc.yml Adds TOC entry for the new breaking change article in the SDK section
docs/core/compatibility/10.0.md Adds table entry for the new breaking change in the SDK and MSBuild section

@nohwnd
Copy link
Member

nohwnd commented Nov 5, 2025

done.

gewarren and others added 2 commits November 5, 2025 11:10
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Clarified the impact of dynamic native instrumentation on process crashes and mentioned that it is disabled by default in certain scenarios. Updated recommendations for handling code coverage with native components.
@gewarren gewarren merged commit af3107c into main Nov 6, 2025
11 checks passed
@gewarren gewarren deleted the copilot/fix-code-coverage-instrumentation branch November 6, 2025 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Breaking change]: Code coverage EnableDynamicNativeInstrumentation is set to false

4 participants