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
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:
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
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