Skip to content

WriteLinesToFile's WriteOnlyWhenDifferent=true does not work when Encoding is provided #14071

Description

@MichalSzkl

Issue Description

WriteLinesToFile task allows one to specify encoding, like UTF-8 or Unicode. This however breaks the WriteOnlyWhenDifferent=true mode, as the code that handles this logic does not even take the encoding parameter, so it tries to use the default utf-8 without BOM for equality purposes
The encoding is properly used when reading and writing the file outside of comparison for WriteOnlyWhenDifferent's purposes

Steps to Reproduce

minimal.zip

Consider attached project. Running it with "MSBuild.exe" /t:CustomTestStep first time causes both targets to execute:

MSBuild version 18.6.3+84d3e95b4 for .NET Framework
Build started 15.06.2026 15:56:47.

Project "minimal\repro.vcxproj" on node 1 (CustomTestStep target(s)).
PreCustomTestStep:
  Executing pre test step
CustomTestStep:
  Executing custom test step
Done Building Project "minimal\repro.vcxproj" (CustomTestStep target(s)).

However, on second run, the CustomTestStep still executes and the should_not_be_changed.txt is rewritten

Expected Behavior

On second run, the CustomTestStep should be skipped

MSBuild version 18.6.3+84d3e95b4 for .NET Framework
Build started 15.06.2026 15:59:30.

Project "minimal\repro.vcxproj" on node 1 (CustomTestStep target(s)).
PreCustomTestStep:
  Executing pre test step
CustomTestStep:
Skipping target "CustomTestStep" because all output files are up-to-date with respect to the input files.
Done Building Project "minimal\repro.vcxproj" (CustomTestStep target(s)).

Actual Behavior

The second task executes anyway

Analysis

There are two problems that compound to this problem, inside the https://github.com/dotnet/msbuild/blob/main/src/Tasks/FileIO/WriteLinesToFile.cs

The main problem is in the FilesAreIdentical method, as it does not take the Encoding encoding variable (that was initialized at https://github.com/dotnet/msbuild/blob/main/src/Tasks/FileIO/WriteLinesToFile.cs#L113) and instead uses the default s_defaultEncoding. This means that providing any custom encoding fails, as the encoded content is compared against utf-8 encoded one. Later, the custom encoding is respected when writing the file and on subsequent runs, the content is again compared between custom-encoded data and utf-8

The second problem is that even if proper encoding is passed to FilesAreIdentical, this method ignores the encoding.GetPreamble() bytes, so if the encoding defines anything (like Unicode or Utf-8 do), the files won't match anyway.

The solution would be to properly pass the encoding all the way down to FilesAreIdentical and then also take the encoding.GetPreamble() into consideration

fix.patch
It could be fixed like this, but this patch is bit yank, so feel free to rewrite it to something better. I also have no idea how to add tests to this project

Versions & Configurations

The error was noticed after migration to Visual Studio 2026

D:\tools>"C:\Program Files\Microsoft Visual Studio\18\Professional\MSBuild\Current\Bin\MSBuild.exe" --version
MSBuild version 18.6.3+84d3e95b4 for .NET Framework
18.6.3.22110

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Area: TasksIssues impacting the tasks shipped in Microsoft.Build.Tasks.Core.dll.triaged

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions