diff --git a/documentation/wiki/MSBuild-Environment-Variables.md b/documentation/wiki/MSBuild-Environment-Variables.md
index 76b73f435f4..f2df570ea77 100644
--- a/documentation/wiki/MSBuild-Environment-Variables.md
+++ b/documentation/wiki/MSBuild-Environment-Variables.md
@@ -34,3 +34,5 @@ Some of the env variables listed here are unsupported, meaning there is no guara
- Set this to force all tasks to run out of process (except inline tasks).
- `MSBUILDFORCEINLINETASKFACTORIESOUTOFPROC`
- Set this to force all inline tasks to run out of process. It is not compatible with custom TaskFactories.
+- `CONSOLE_USE_DEFAULT_ENCODING`
+ - It opts out automatic console encoding UTF-8. Make Console use default encoding in the system.
\ No newline at end of file
diff --git a/src/Framework/Traits.cs b/src/Framework/Traits.cs
index 8cbf21feef1..029d74448a9 100644
--- a/src/Framework/Traits.cs
+++ b/src/Framework/Traits.cs
@@ -147,6 +147,11 @@ public Traits()
///
public readonly bool ForceTaskFactoryOutOfProc = Environment.GetEnvironmentVariable("MSBUILDFORCEINLINETASKFACTORIESOUTOFPROC") == "1";
+ ///
+ /// Make Console use default encoding in the system. It opts out automatic console encoding UTF-8.
+ ///
+ public readonly bool ConsoleUseDefaultEncoding = Environment.GetEnvironmentVariable("CONSOLE_USE_DEFAULT_ENCODING") == "1";
+
///
/// Variables controlling opt out at the level of not initializing telemetry infrastructure. Set to "1" or "true" to opt out.
/// mirroring
diff --git a/src/MSBuild/XMake.cs b/src/MSBuild/XMake.cs
index 7febc492d7a..ffd58665a96 100644
--- a/src/MSBuild/XMake.cs
+++ b/src/MSBuild/XMake.cs
@@ -1934,23 +1934,26 @@ internal static void SetConsoleUI()
CultureInfo.CurrentUICulture = desiredCulture;
CultureInfo.DefaultThreadCurrentUICulture = desiredCulture;
+ if (!Traits.Instance.ConsoleUseDefaultEncoding)
+ {
#if RUNTIME_TYPE_NETCORE
- if (EncodingUtilities.CurrentPlatformIsWindowsAndOfficiallySupportsUTF8Encoding())
+ if (EncodingUtilities.CurrentPlatformIsWindowsAndOfficiallySupportsUTF8Encoding())
#else
- if (EncodingUtilities.CurrentPlatformIsWindowsAndOfficiallySupportsUTF8Encoding()
- && !CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("en", StringComparison.InvariantCultureIgnoreCase))
+ if (EncodingUtilities.CurrentPlatformIsWindowsAndOfficiallySupportsUTF8Encoding()
+ && !CultureInfo.CurrentUICulture.TwoLetterISOLanguageName.Equals("en", StringComparison.InvariantCultureIgnoreCase))
#endif
- {
- try
- {
- // Setting both encodings causes a change in the CHCP, making it so we don't need to P-Invoke CHCP ourselves.
- Console.OutputEncoding = Encoding.UTF8;
- // If the InputEncoding is not set, the encoding will work in CMD but not in PowerShell, as the raw CHCP page won't be changed.
- Console.InputEncoding = Encoding.UTF8;
- }
- catch (Exception ex) when (ex is IOException || ex is SecurityException)
{
- // The encoding is unavailable. Do nothing.
+ try
+ {
+ // Setting both encodings causes a change in the CHCP, making it so we don't need to P-Invoke CHCP ourselves.
+ Console.OutputEncoding = Encoding.UTF8;
+ // If the InputEncoding is not set, the encoding will work in CMD but not in PowerShell, as the raw CHCP page won't be changed.
+ Console.InputEncoding = Encoding.UTF8;
+ }
+ catch (Exception ex) when (ex is IOException || ex is SecurityException)
+ {
+ // The encoding is unavailable. Do nothing.
+ }
}
}