diff --git a/src/corehost/cli/apphost/CMakeLists.txt b/src/corehost/cli/apphost/CMakeLists.txt
index cc610cd119..4dac1f30ec 100644
--- a/src/corehost/cli/apphost/CMakeLists.txt
+++ b/src/corehost/cli/apphost/CMakeLists.txt
@@ -26,3 +26,10 @@ include(../exe.cmake)
add_definitions(-DFEATURE_APPHOST=1)
install_library_and_symbols (apphost)
+
+# Disable manifest generation into the file .exe on Windows
+if(WIN32)
+ set_property(TARGET ${PROJECT_NAME} PROPERTY
+ LINK_FLAGS "/MANIFEST:NO"
+ )
+endif()
\ No newline at end of file
diff --git a/src/corehost/cli/dotnet/CMakeLists.txt b/src/corehost/cli/dotnet/CMakeLists.txt
index 5b3b392666..fa666cf57f 100644
--- a/src/corehost/cli/dotnet/CMakeLists.txt
+++ b/src/corehost/cli/dotnet/CMakeLists.txt
@@ -6,6 +6,12 @@ project(dotnet)
set(DOTNET_HOST_EXE_NAME "dotnet")
set(SOURCES
../fxr/fx_ver.cpp)
+
+if(WIN32)
+ list(APPEND SOURCES
+ dotnet.manifest)
+endif()
+
include(../exe.cmake)
install_library_and_symbols (dotnet)
diff --git a/src/corehost/cli/dotnet/dotnet.manifest b/src/corehost/cli/dotnet/dotnet.manifest
new file mode 100644
index 0000000000..caf8501d6a
--- /dev/null
+++ b/src/corehost/cli/dotnet/dotnet.manifest
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/Assets/TestProjects/TestWindowsOsShimsApp/Program.cs b/src/test/Assets/TestProjects/TestWindowsOsShimsApp/Program.cs
new file mode 100644
index 0000000000..79238addbf
--- /dev/null
+++ b/src/test/Assets/TestProjects/TestWindowsOsShimsApp/Program.cs
@@ -0,0 +1,149 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace TestWindowsOsShimsApp
+{
+ public static class Program
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("Hello World!");
+ Console.WriteLine(string.Join(Environment.NewLine, args));
+ Console.WriteLine($"Framework Version:{GetFrameworkVersionFromAppDomain()}");
+
+ #if WINDOWS
+ Version osVersion = RtlGetVersion();
+ if (osVersion == null)
+ {
+ Console.WriteLine("Failed to get OS version through RtlGetVersion.");
+ }
+ else
+ {
+ Console.WriteLine($"Detected true OS version: {osVersion.Major}.{osVersion.Minor}");
+ if (OsVersionIsNewerThan(osVersion))
+ {
+ Console.WriteLine($"Reported OS version is newer or equal to the true OS version - no shims.");
+ }
+ else
+ {
+ Console.WriteLine($"Reported OS version is lower than the true OS version - shims in use.");
+ }
+ }
+ #endif
+ }
+
+ private static string GetFrameworkVersionFromAppDomain()
+ {
+ return System.AppDomain.CurrentDomain.GetData("FX_PRODUCT_VERSION") as string;
+ }
+
+#if WINDOWS
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal struct OSVERSIONINFOEX
+ {
+
+ internal uint dwOSVersionInfoSize;
+ internal uint dwMajorVersion;
+ internal uint dwMinorVersion;
+ internal uint dwBuildNumber;
+ internal uint dwPlatformId;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] //
+ internal string szCSDVersion;
+ internal ushort wServicePackMajor;
+ internal ushort wServicePackMinor;
+ internal ushort wSuiteMask;
+ internal byte wProductType;
+ internal byte wReserved;
+ }
+
+ [Flags]
+ enum ConditionMask : byte
+ {
+ VER_EQUAL = 1,
+ VER_GREATER = 2,
+ VER_GREATER_EQUAL = 3,
+ VER_LESS = 4,
+ VER_LESS_EQUAL = 5,
+ VER_AND = 6,
+ VER_OR = 7
+ }
+
+ [Flags]
+ enum TypeMask : uint
+ {
+ VER_MINORVERSION = 0x0000001,
+ VER_MAJORVERSION = 0x0000002,
+ VER_BUILDNUMBER = 0x0000004,
+ VER_PLATFORMID = 0x0000008,
+ VER_SERVICEPACKMINOR = 0x0000010,
+ VER_SERVICEPACKMAJOR = 0x0000020,
+ VER_SUITENAME = 0x0000040,
+ VER_PRODUCT_TYPE = 0x0000080
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal unsafe struct RTL_OSVERSIONINFOEX
+ {
+ internal uint dwOSVersionInfoSize;
+ internal uint dwMajorVersion;
+ internal uint dwMinorVersion;
+ internal uint dwBuildNumber;
+ internal uint dwPlatformId;
+ internal fixed char szCSDVersion[128];
+ }
+
+ [DllImport("ntdll.dll", ExactSpelling=true)]
+ private static extern int RtlGetVersion(ref RTL_OSVERSIONINFOEX lpVersionInformation);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool VerifyVersionInfo(ref OSVERSIONINFOEX lpVersionInfo, TypeMask dwTypeMask, ulong dwlConditionMask);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
+ private static extern ulong VerSetConditionMask(ulong dwlConditionMask, TypeMask dwTypeBitMask, ConditionMask dwConditionMask);
+
+ internal unsafe static int RtlGetVersionEx(out RTL_OSVERSIONINFOEX osvi)
+ {
+ osvi = new RTL_OSVERSIONINFOEX();
+ osvi.dwOSVersionInfoSize = (uint)sizeof(RTL_OSVERSIONINFOEX);
+ return RtlGetVersion(ref osvi);
+ }
+
+ internal static Version RtlGetVersion()
+ {
+ if (RtlGetVersionEx(out RTL_OSVERSIONINFOEX osvi) == 0)
+ {
+ return new Version((int)osvi.dwMajorVersion, (int)osvi.dwMinorVersion);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ internal static bool OsVersionIsNewerThan(Version osVersion)
+ {
+ // check if newer than
+ OSVERSIONINFOEX osv = new OSVERSIONINFOEX()
+ {
+ dwOSVersionInfoSize = (uint)Marshal.SizeOf(),
+ dwMajorVersion = (uint)osVersion.Major,
+ dwMinorVersion = (uint)osVersion.Minor
+ };
+
+ var conditionMask = 0uL;
+ conditionMask = VerSetConditionMask(conditionMask, TypeMask.VER_MAJORVERSION, ConditionMask.VER_GREATER_EQUAL);
+ conditionMask = VerSetConditionMask(conditionMask, TypeMask.VER_MINORVERSION, ConditionMask.VER_GREATER_EQUAL);
+
+ if (VerifyVersionInfo(ref osv, TypeMask.VER_MAJORVERSION | TypeMask.VER_MINORVERSION, conditionMask))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+#endif
+ }
+}
diff --git a/src/test/Assets/TestProjects/TestWindowsOsShimsApp/TestWindowsOsShimsApp.csproj b/src/test/Assets/TestProjects/TestWindowsOsShimsApp/TestWindowsOsShimsApp.csproj
new file mode 100644
index 0000000000..70d4c67081
--- /dev/null
+++ b/src/test/Assets/TestProjects/TestWindowsOsShimsApp/TestWindowsOsShimsApp.csproj
@@ -0,0 +1,12 @@
+
+
+
+ $(NETCoreAppFramework)
+ $(TestTargetRid)
+ Exe
+ $(MNAVersion)
+ WINDOWS;$(DefineConstants)
+ true
+
+
+
diff --git a/src/test/HostActivationTests/GivenThatICareAboutWindowsOsShims.cs b/src/test/HostActivationTests/GivenThatICareAboutWindowsOsShims.cs
new file mode 100644
index 0000000000..559d987139
--- /dev/null
+++ b/src/test/HostActivationTests/GivenThatICareAboutWindowsOsShims.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Runtime.InteropServices;
+using Xunit;
+
+namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.WindowsOsShims
+{
+ public class GivenThatICareAboutWindowsOsShims : IClassFixture
+ {
+ private SharedTestState sharedTestState;
+
+ public GivenThatICareAboutWindowsOsShims(SharedTestState fixture)
+ {
+ sharedTestState = fixture;
+ }
+
+ [Fact]
+ public void MuxerRunsPortableAppWithoutWindowsOsShims()
+ {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ // Manifests are only supported on Windows OSes.
+ return;
+ }
+
+ TestProjectFixture portableAppFixture = sharedTestState.PortableTestWindowsOsShimsAppFixture.Copy();
+
+ portableAppFixture.BuiltDotnet.Exec(portableAppFixture.TestProject.AppDll)
+ .CaptureStdErr()
+ .CaptureStdOut()
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOutContaining("Reported OS version is newer or equal to the true OS version - no shims.");
+ }
+
+ // Testing the standalone version (apphost) would require to make a copy of the entire SDK
+ // and overwrite the apphost.exe in it. Currently this is just too expensive for one test (160MB of data).
+
+ public class SharedTestState : IDisposable
+ {
+ private static RepoDirectoriesProvider RepoDirectories { get; set; }
+
+ public TestProjectFixture PortableTestWindowsOsShimsAppFixture { get; set; }
+
+ public SharedTestState()
+ {
+ RepoDirectories = new RepoDirectoriesProvider();
+
+ PortableTestWindowsOsShimsAppFixture = new TestProjectFixture("TestWindowsOsShimsApp", RepoDirectories)
+ .EnsureRestored(RepoDirectories.CorehostPackages)
+ .PublishProject();
+ }
+
+ public void Dispose()
+ {
+ PortableTestWindowsOsShimsAppFixture.Dispose();
+ }
+ }
+ }
+}