diff --git a/src/installer/tests/HostActivation.Tests/FrameworkResolution/DotNetCliExtensions.cs b/src/installer/tests/HostActivation.Tests/FrameworkResolution/DotNetCliExtensions.cs index 5a8830556f54b6..6f637a1f586907 100644 --- a/src/installer/tests/HostActivation.Tests/FrameworkResolution/DotNetCliExtensions.cs +++ b/src/installer/tests/HostActivation.Tests/FrameworkResolution/DotNetCliExtensions.cs @@ -77,7 +77,7 @@ public DotNetFramework RuntimeConfig(Action runtimeConfigCustomiz { string runtimeConfigPath = Path.Combine(_path, _name + ".runtimeconfig.json"); _backup.Backup(runtimeConfigPath); - RuntimeConfig runtimeConfig = HostActivation.RuntimeConfig.FromFile(runtimeConfigPath); + RuntimeConfig runtimeConfig = Test.RuntimeConfig.FromFile(runtimeConfigPath); runtimeConfigCustomizer(runtimeConfig); runtimeConfig.Save(); diff --git a/src/installer/tests/HostActivation.Tests/HostActivation.Tests.csproj b/src/installer/tests/HostActivation.Tests/HostActivation.Tests.csproj index 55c14ce9d5a6b5..9724d3326e75a0 100644 --- a/src/installer/tests/HostActivation.Tests/HostActivation.Tests.csproj +++ b/src/installer/tests/HostActivation.Tests/HostActivation.Tests.csproj @@ -5,7 +5,6 @@ HostActivation.Tests HostActivation.Tests true - $(DefineConstants);WINDOWS ha true @@ -17,7 +16,6 @@ - diff --git a/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs b/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs index 4b1b28e32f3ee2..12a03c9de130ef 100644 --- a/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs +++ b/src/installer/tests/HostActivation.Tests/PortableAppActivation.cs @@ -526,7 +526,7 @@ public void AppHost_GUI_FrameworkDependent_MissingRuntimeFramework_ErrorReported .MultilevelLookup(false) .Start(); - WaitForPopupFromProcess(command.Process); + WindowsUtils.WaitForPopupFromProcess(command.Process); command.Process.Kill(); var result = command.WaitForExit(true) @@ -559,7 +559,7 @@ public void AppHost_GUI_MissingRuntime_ErrorReportedInDialog() .MultilevelLookup(false) .Start(); - WaitForPopupFromProcess(command.Process); + WindowsUtils.WaitForPopupFromProcess(command.Process); command.Process.Kill(); var expectedErrorCode = Constants.ErrorCode.CoreHostLibMissingFailure.ToString("x"); @@ -601,7 +601,7 @@ public void AppHost_GUI_NoCustomErrorWriter_FrameworkMissing_ErrorReportedInDial .MultilevelLookup(false) .Start(); - WaitForPopupFromProcess(command.Process); + WindowsUtils.WaitForPopupFromProcess(command.Process); command.Process.Kill(); command.WaitForExit(true) @@ -689,50 +689,6 @@ private string CreateAStore(TestProjectFixture testProjectFixture) return storeoutputDirectory; } -#if WINDOWS - private delegate bool EnumThreadWindowsDelegate(IntPtr hWnd, IntPtr lParam); - - [DllImport("user32.dll")] - private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadWindowsDelegate plfn, IntPtr lParam); - - private IntPtr WaitForPopupFromProcess(Process process, int timeout = 60000) - { - IntPtr windowHandle = IntPtr.Zero; - int timeRemaining = timeout; - while (timeRemaining > 0) - { - foreach (ProcessThread thread in process.Threads) - { - // We take the last window we find. There really should only be one at most anyways. - EnumThreadWindows(thread.Id, - (hWnd, lParam) => { - windowHandle = hWnd; - return true; - }, - IntPtr.Zero); - } - - if (windowHandle != IntPtr.Zero) - { - break; - } - - System.Threading.Thread.Sleep(100); - timeRemaining -= 100; - } - - // Do not fail if the window could be detected, sometimes the check is fragile and doesn't work. - // Not worth the trouble trying to figure out why (only happens rarely in the CI system). - // We will rely on product tracing in the failure case. - return windowHandle; - } -#else - private IntPtr WaitForPopupFromProcess(Process process, int timeout = 60000) - { - throw new PlatformNotSupportedException(); - } -#endif - public class SharedTestState : IDisposable { public TestProjectFixture PortableAppFixture_Built { get; } diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs index 66212592138151..b3eb84c48f8bac 100644 --- a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs +++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundledAppWithSubDirs.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.IO; using BundleTests.Helpers; using Microsoft.DotNet.Cli.Build.Framework; using Microsoft.DotNet.CoreSetup.Test; @@ -22,9 +23,7 @@ public BundledAppWithSubDirs(SharedTestState fixture) private void RunTheApp(string path, TestProjectFixture fixture) { Command.Create(path) - .EnvironmentVariable("COREHOST_TRACE", "1") - .CaptureStdErr() - .CaptureStdOut() + .EnableTracingAndCaptureOutputs() .EnvironmentVariable("DOTNET_ROOT", fixture.BuiltDotnet.BinPath) .EnvironmentVariable("DOTNET_ROOT(x86)", fixture.BuiltDotnet.BinPath) .EnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0") @@ -52,6 +51,46 @@ public void Bundled_Framework_dependent_App_Run_Succeeds(BundleOptions options) RunTheApp(singleFile, fixture); } + [InlineData(BundleOptions.None)] + [InlineData(BundleOptions.BundleNativeBinaries)] + [InlineData(BundleOptions.BundleAllContent)] + [Theory] + [PlatformSpecific(TestPlatforms.Windows)] // GUI app host is only supported on Windows. + public void Bundled_Framework_dependent_App_GUI_DownlevelHostFxr_ErrorDialog(BundleOptions options) + { + var fixture = sharedTestState.TestFrameworkDependentFixture.Copy(); + UseFrameworkDependentHost(fixture); + var singleFile = BundleHelper.BundleApp(fixture, options); + AppHostExtensions.SetWindowsGraphicalUserInterfaceBit(singleFile); + + string dotnetWithMockHostFxr = SharedFramework.CalculateUniqueTestDirectory(Path.Combine(TestArtifact.TestArtifactsPath, "bundleErrors")); + using (new TestArtifact(dotnetWithMockHostFxr)) + { + Directory.CreateDirectory(dotnetWithMockHostFxr); + string expectedErrorCode = Constants.ErrorCode.BundleExtractionFailure.ToString("x"); + + var dotnetBuilder = new DotNetBuilder(dotnetWithMockHostFxr, sharedTestState.RepoDirectories.BuiltDotnet, "hostfxrFrameworkMissingFailure") + .RemoveHostFxr() + .AddMockHostFxr(new Version(5, 0, 0)); + var dotnet = dotnetBuilder.Build(); + + Command command = Command.Create(singleFile) + .EnableTracingAndCaptureOutputs() + .DotNetRoot(dotnet.BinPath, sharedTestState.RepoDirectories.BuildArchitecture) + .MultilevelLookup(false) + .Start(); + + WindowsUtils.WaitForPopupFromProcess(command.Process); + command.Process.Kill(); + + command + .WaitForExit(true) + .Should().Fail() + .And.HaveStdErrContaining("Bundle header version compatibility check failed.") + .And.HaveStdErrContaining($"Showing error dialog for application: '{Path.GetFileName(singleFile)}' - error code: 0x{expectedErrorCode}"); + } + } + [InlineData(BundleOptions.None)] [InlineData(BundleOptions.BundleNativeBinaries)] [InlineData(BundleOptions.BundleAllContent)] diff --git a/src/installer/tests/HostActivation.Tests/CommandExtensions.cs b/src/installer/tests/TestUtils/CommandExtensions.cs similarity index 81% rename from src/installer/tests/HostActivation.Tests/CommandExtensions.cs rename to src/installer/tests/TestUtils/CommandExtensions.cs index d8460c1368bdb5..38c4cbff3ba448 100644 --- a/src/installer/tests/HostActivation.Tests/CommandExtensions.cs +++ b/src/installer/tests/TestUtils/CommandExtensions.cs @@ -2,10 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.DotNet.CoreSetup.Test; using System; using System.IO; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { public static class CommandExtensions { @@ -38,11 +39,11 @@ public static Command EnableTracingAndCaptureOutputs(this Command command) public static Command DotNetRoot(this Command command, string dotNetRoot, string architecture = null) { if (!string.IsNullOrEmpty(architecture)) - return command.EnvironmentVariable($"DOTNET_ROOT_{architecture.ToUpper()}", dotNetRoot); + return command.EnvironmentVariable(Constants.DotnetRoot.ArchitectureEnvironmentVariablePrefix + architecture.ToUpper(), dotNetRoot); return command - .EnvironmentVariable("DOTNET_ROOT", dotNetRoot) - .EnvironmentVariable("DOTNET_ROOT(x86)", dotNetRoot); + .EnvironmentVariable(Constants.DotnetRoot.EnvironmentVariable, dotNetRoot) + .EnvironmentVariable(Constants.DotnetRoot.WindowsX86EnvironmentVariable, dotNetRoot); } public static Command MultilevelLookup(this Command command, bool enable) diff --git a/src/installer/tests/HostActivation.Tests/Constants.cs b/src/installer/tests/TestUtils/Constants.cs similarity index 88% rename from src/installer/tests/HostActivation.Tests/Constants.cs rename to src/installer/tests/TestUtils/Constants.cs index 25768a5698273b..e36df4bd2cdb39 100644 --- a/src/installer/tests/HostActivation.Tests/Constants.cs +++ b/src/installer/tests/TestUtils/Constants.cs @@ -1,9 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { - internal static class Constants + public static class Constants { public const string MicrosoftNETCoreApp = "Microsoft.NETCore.App"; @@ -72,6 +72,13 @@ public static class HostTracing public const string TraceFileEnvironmentVariable = "COREHOST_TRACEFILE"; } + public static class DotnetRoot + { + public const string EnvironmentVariable = "DOTNET_ROOT"; + public const string WindowsX86EnvironmentVariable = "DOTNET_ROOT(x86)"; + public const string ArchitectureEnvironmentVariablePrefix = "DOTNET_ROOT_"; + } + public static class ErrorCode { public const int InvalidArgFailure = unchecked((int)0x80008081); @@ -81,6 +88,7 @@ public static class ErrorCode public const int LibHostInvalidArgs = unchecked((int)0x80008092); public const int AppArgNotRunnable = unchecked((int)0x80008094); public const int FrameworkMissingFailure = unchecked((int)0x80008096); + public const int BundleExtractionFailure = unchecked((int)0x8000809f); public const int COMPlusException = unchecked((int)0xe0434352); public const int SIGABRT = 134; diff --git a/src/installer/tests/HostActivation.Tests/DotNetBuilder.cs b/src/installer/tests/TestUtils/DotNetBuilder.cs similarity index 95% rename from src/installer/tests/HostActivation.Tests/DotNetBuilder.cs rename to src/installer/tests/TestUtils/DotNetBuilder.cs index 0a8d54559e2275..d4cb58340ca6ed 100644 --- a/src/installer/tests/HostActivation.Tests/DotNetBuilder.cs +++ b/src/installer/tests/TestUtils/DotNetBuilder.cs @@ -5,7 +5,7 @@ using System; using System.IO; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { /// /// Helper class for creating a mock version of a dotnet installation @@ -68,16 +68,19 @@ public DotNetBuilder AddMicrosoftNETCoreAppFrameworkMockHostPolicy(string versio /// Use a mock version of HostFxr. /// /// Version to add - /// - /// Currently, the only mock version of HostFxr that we have is mockhostfxr_2_2. - /// public DotNetBuilder AddMockHostFxr(Version version) { string hostfxrPath = Path.Combine(_path, "host", "fxr", version.ToString()); Directory.CreateDirectory(hostfxrPath); - bool hasCustomErrorWriter = version.Major >= 3; - string mockHostFxrFileName = RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform(hasCustomErrorWriter ? "mockhostfxr" : "mockhostfxr_2_2"); + string mockHostFxrFileNameBase = version switch + { + { Major: 2, Minor: 2 } => "mockhostfxr_2_2", + { Major: 5, Minor: 0 } => "mockhostfxr_5_0", + _ => throw new InvalidOperationException($"Unsupported version {version} of mockhostfxr.") + }; + + string mockHostFxrFileName = RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform(mockHostFxrFileNameBase); File.Copy( Path.Combine(_repoDirectories.Artifacts, "corehost_test", mockHostFxrFileName), Path.Combine(hostfxrPath, RuntimeInformationExtensions.GetSharedLibraryFileNameForCurrentPlatform("hostfxr")), diff --git a/src/installer/tests/TestUtils/FileUtils.cs b/src/installer/tests/TestUtils/FileUtils.cs index 8da68f684734bf..a66ead73e0b026 100644 --- a/src/installer/tests/TestUtils/FileUtils.cs +++ b/src/installer/tests/TestUtils/FileUtils.cs @@ -5,7 +5,7 @@ using System.IO; using System.IO.MemoryMappedFiles; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { public static class FileUtils { diff --git a/src/installer/tests/HostActivation.Tests/NetCoreAppBuilder.cs b/src/installer/tests/TestUtils/NetCoreAppBuilder.cs similarity index 99% rename from src/installer/tests/HostActivation.Tests/NetCoreAppBuilder.cs rename to src/installer/tests/TestUtils/NetCoreAppBuilder.cs index ba5e101558c29d..f4909cde996799 100644 --- a/src/installer/tests/HostActivation.Tests/NetCoreAppBuilder.cs +++ b/src/installer/tests/TestUtils/NetCoreAppBuilder.cs @@ -7,7 +7,7 @@ using System.IO; using System.Linq; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { public class NetCoreAppBuilder { diff --git a/src/installer/tests/HostActivation.Tests/RuntimeConfig.cs b/src/installer/tests/TestUtils/RuntimeConfig.cs similarity index 99% rename from src/installer/tests/HostActivation.Tests/RuntimeConfig.cs rename to src/installer/tests/TestUtils/RuntimeConfig.cs index eaa95cb2dcced0..2a8418f4713280 100644 --- a/src/installer/tests/HostActivation.Tests/RuntimeConfig.cs +++ b/src/installer/tests/TestUtils/RuntimeConfig.cs @@ -8,7 +8,7 @@ using System.IO; using System.Linq; -namespace Microsoft.DotNet.CoreSetup.Test.HostActivation +namespace Microsoft.DotNet.CoreSetup.Test { public class RuntimeConfig { diff --git a/src/installer/tests/HostActivation.Tests/SharedFramework.cs b/src/installer/tests/TestUtils/SharedFramework.cs similarity index 99% rename from src/installer/tests/HostActivation.Tests/SharedFramework.cs rename to src/installer/tests/TestUtils/SharedFramework.cs index a887b2bf65160a..408cf58f37b4e1 100644 --- a/src/installer/tests/HostActivation.Tests/SharedFramework.cs +++ b/src/installer/tests/TestUtils/SharedFramework.cs @@ -10,7 +10,7 @@ namespace Microsoft.DotNet.CoreSetup.Test /// /// Helper class for creating, modifying and cleaning up shared frameworks /// - internal static class SharedFramework + public static class SharedFramework { private static readonly Mutex id_mutex = new Mutex(); diff --git a/src/installer/tests/TestUtils/TestArtifact.cs b/src/installer/tests/TestUtils/TestArtifact.cs index 8483e4c88f7a8a..e1ca67416377ee 100644 --- a/src/installer/tests/TestUtils/TestArtifact.cs +++ b/src/installer/tests/TestUtils/TestArtifact.cs @@ -3,7 +3,6 @@ #nullable enable -using Microsoft.DotNet.CoreSetup.Test.HostActivation; using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/src/installer/tests/TestUtils/TestUtils.csproj b/src/installer/tests/TestUtils/TestUtils.csproj index 35cb3e19e9d77a..1ca28978738f78 100644 --- a/src/installer/tests/TestUtils/TestUtils.csproj +++ b/src/installer/tests/TestUtils/TestUtils.csproj @@ -15,6 +15,8 @@ + + diff --git a/src/installer/tests/TestUtils/WindowsUtils.cs b/src/installer/tests/TestUtils/WindowsUtils.cs new file mode 100644 index 00000000000000..aff4c1fef8297b --- /dev/null +++ b/src/installer/tests/TestUtils/WindowsUtils.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Microsoft.DotNet.CoreSetup.Test +{ + public static class WindowsUtils + { + private delegate bool EnumThreadWindowsDelegate(IntPtr hWnd, IntPtr lParam); + + [DllImport("user32.dll")] + private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadWindowsDelegate plfn, IntPtr lParam); + + public static IntPtr WaitForPopupFromProcess(Process process, int timeout = 60000) + { + if (!OperatingSystem.IsWindows()) + { + throw new PlatformNotSupportedException(); + } + + IntPtr windowHandle = IntPtr.Zero; + int timeRemaining = timeout; + while (timeRemaining > 0) + { + foreach (ProcessThread thread in process.Threads) + { + // We take the last window we find. There really should only be one at most anyways. + EnumThreadWindows(thread.Id, + (hWnd, lParam) => { + windowHandle = hWnd; + return true; + }, + IntPtr.Zero); + } + + if (windowHandle != IntPtr.Zero) + { + break; + } + + System.Threading.Thread.Sleep(100); + timeRemaining -= 100; + } + + // Do not fail if the window could be detected, sometimes the check is fragile and doesn't work. + // Not worth the trouble trying to figure out why (only happens rarely in the CI system). + // We will rely on product tracing in the failure case. + return windowHandle; + } + } +} diff --git a/src/native/corehost/apphost/apphost.windows.cpp b/src/native/corehost/apphost/apphost.windows.cpp index b6c229e93086a1..5e16d06ac7435e 100644 --- a/src/native/corehost/apphost/apphost.windows.cpp +++ b/src/native/corehost/apphost/apphost.windows.cpp @@ -52,11 +52,6 @@ namespace void show_error_dialog(const pal::char_t *executable_name, int error_code) { - // Show message dialog for UI apps with actionable errors - if (error_code != StatusCode::CoreHostLibMissingFailure // missing hostfxr - && error_code != StatusCode::FrameworkMissingFailure) // missing framework - return; - pal::string_t gui_errors_disabled; if (pal::getenv(_X("DOTNET_DISABLE_GUI_ERRORS"), &gui_errors_disabled) && pal::xtoi(gui_errors_disabled.c_str()) == 1) return; @@ -108,6 +103,23 @@ namespace } } } + else if (error_code == StatusCode::BundleExtractionFailure) + { + pal::string_t line; + pal::stringstream_t ss(g_buffered_errors); + while (std::getline(ss, line, _X('\n'))) { + if (starts_with(line, _X("Bundle header version compatibility check failed."), true)) + { + dialogMsg = pal::string_t(_X("To run this application, you must install .NET Desktop Runtime ")) + _STRINGIFY(COMMON_HOST_PKG_VER) + _X(" (") + get_arch() + _X(").\n\n"); + url = get_download_url(); + } + } + + if (dialogMsg.empty()) + return; + } + else + return; dialogMsg.append(_X("Would you like to download it now?")); diff --git a/src/native/corehost/test/CMakeLists.txt b/src/native/corehost/test/CMakeLists.txt index 84b14039de91ee..a0ddc276223ed3 100644 --- a/src/native/corehost/test/CMakeLists.txt +++ b/src/native/corehost/test/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(fx_ver) add_subdirectory(mockcoreclr) -add_subdirectory(mockhostfxr) +add_subdirectory(mockhostfxr/2_2) +add_subdirectory(mockhostfxr/5_0) add_subdirectory(mockhostpolicy) add_subdirectory(nativehost) if (CLR_CMAKE_TARGET_WIN32) diff --git a/src/native/corehost/test/mockhostfxr/CMakeLists.txt b/src/native/corehost/test/mockhostfxr/2_2/CMakeLists.txt similarity index 76% rename from src/native/corehost/test/mockhostfxr/CMakeLists.txt rename to src/native/corehost/test/mockhostfxr/2_2/CMakeLists.txt index 8b5a55fe9b1772..096c3631afbc8c 100644 --- a/src/native/corehost/test/mockhostfxr/CMakeLists.txt +++ b/src/native/corehost/test/mockhostfxr/2_2/CMakeLists.txt @@ -5,10 +5,12 @@ project(mockhostfxr_2_2) set(DOTNET_PROJECT_NAME "mockhostfxr_2_2") +add_definitions(-D_MOCKHOSTFXR_2_2) + set(SOURCES - ./mockhostfxr.cpp + ./../mockhostfxr.cpp ) -include(../testlib.cmake) +include(../../testlib.cmake) install_with_stripped_symbols(mockhostfxr_2_2 TARGETS corehost_test) diff --git a/src/native/corehost/test/mockhostfxr/5_0/CMakeLists.txt b/src/native/corehost/test/mockhostfxr/5_0/CMakeLists.txt new file mode 100644 index 00000000000000..5f9f36c71852a5 --- /dev/null +++ b/src/native/corehost/test/mockhostfxr/5_0/CMakeLists.txt @@ -0,0 +1,16 @@ +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. + +project(mockhostfxr_5_0) + +set(DOTNET_PROJECT_NAME "mockhostfxr_5_0") + +add_definitions(-DMOCKHOSTFXR_5_0) + +set(SOURCES + ./../mockhostfxr.cpp +) + +include(../../testlib.cmake) + +install_with_stripped_symbols(mockhostfxr_5_0 TARGETS corehost_test) diff --git a/src/native/corehost/test/mockhostfxr/mockhostfxr.cpp b/src/native/corehost/test/mockhostfxr/mockhostfxr.cpp index a85650bccbd057..bae79db4330ea7 100644 --- a/src/native/corehost/test/mockhostfxr/mockhostfxr.cpp +++ b/src/native/corehost/test/mockhostfxr/mockhostfxr.cpp @@ -27,3 +27,27 @@ SHARED_API int HOSTFXR_CALLTYPE hostfxr_main_startupinfo(const int argc, const p return StatusCode::Success; } + +#ifdef MOCKHOSTFXR_5_0 +SHARED_API hostfxr_error_writer_fn HOSTFXR_CALLTYPE hostfxr_set_error_writer(hostfxr_error_writer_fn error_writer) +{ + return trace::set_error_writer(error_writer); +} + +SHARED_API int HOSTFXR_CALLTYPE hostfxr_main_bundle_startupinfo(const int argc, const pal::char_t* argv[], const pal::char_t* host_path, const pal::char_t* dotnet_root, const pal::char_t* app_path, int64_t bundle_header_offset) +{ + trace_hostfxr_entry_point(_X("hostfxr_main_bundle_startupinfo")); + + const pal::string_t dotnet_folder = get_directory(dotnet_root); + + if (pal::strcmp(dotnet_folder.c_str(), _X("mockhostfxrBundleVersionFailure"))) + { + trace::error(_X("Failure processing application bundle.")); + trace::error(_X("Bundle header version compatibility check failed.")); + + return StatusCode::BundleExtractionFailure; + } + + return StatusCode::Success; +} +#endif