diff --git a/src/installer/tests/Assets/Projects/HostApiInvokerApp/Program.cs b/src/installer/tests/Assets/Projects/HostApiInvokerApp/Program.cs index f14003995e6a2..d586de4aeb7af 100644 --- a/src/installer/tests/Assets/Projects/HostApiInvokerApp/Program.cs +++ b/src/installer/tests/Assets/Projects/HostApiInvokerApp/Program.cs @@ -30,6 +30,10 @@ public static void MainCore(string[] args) { Console.WriteLine("Hello World!"); Console.WriteLine(string.Join(Environment.NewLine, args)); + if (args.Length == 0) + { + throw new Exception("Invalid number of arguments passed"); + } // If requested, test multilevel lookup using fake Global SDK directories: // 1. using a fake ProgramFiles location @@ -39,22 +43,30 @@ public static void MainCore(string[] args) string testMultilevelLookupProgramFiles = Environment.GetEnvironmentVariable("TEST_MULTILEVEL_LOOKUP_PROGRAM_FILES"); string testMultilevelLookupSelfRegistered = Environment.GetEnvironmentVariable("TEST_MULTILEVEL_LOOKUP_SELF_REGISTERED"); + string hostfxrPath; if (testMultilevelLookupProgramFiles != null && testMultilevelLookupSelfRegistered != null) { Environment.SetEnvironmentVariable("_DOTNET_TEST_GLOBALLY_REGISTERED_PATH", testMultilevelLookupSelfRegistered); Environment.SetEnvironmentVariable("ProgramFiles", testMultilevelLookupProgramFiles); Environment.SetEnvironmentVariable("ProgramFiles(x86)", testMultilevelLookupProgramFiles); Environment.SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "1"); + hostfxrPath = AppContext.GetData("HOSTFXR_PATH_TEST_BEHAVIOR") as string; } else { // never rely on machine state in test if we're not faking the multi-level lookup Environment.SetEnvironmentVariable("DOTNET_MULTILEVEL_LOOKUP", "0"); + hostfxrPath = AppContext.GetData("HOSTFXR_PATH") as string; } - if (args.Length == 0) + if (hostfxrPath is not null) { - throw new Exception("Invalid number of arguments passed"); + NativeLibrary.SetDllImportResolver(typeof(Program).Assembly, (libraryName, assembly, searchPath) => + { + return libraryName == nameof(HostFXR.hostfxr) + ? NativeLibrary.Load(libraryName, assembly, searchPath) + : default; + }); } string apiToTest = args[0]; diff --git a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs index b48667ef4012b..685d7e1404dac 100644 --- a/src/installer/tests/HostActivation.Tests/NativeHostApis.cs +++ b/src/installer/tests/HostActivation.Tests/NativeHostApis.cs @@ -768,14 +768,6 @@ public class SharedTestState : IDisposable public SharedTestState() { - HostApiInvokerApp = TestApp.CreateFromBuiltAssets("HostApiInvokerApp"); - - if (!OperatingSystem.IsWindows()) - { - // On non-Windows, we can't just P/Invoke to already loaded hostfxr, so copy it next to the app dll. - File.Copy(Binaries.HostFxr.FilePath, Path.Combine(HostApiInvokerApp.Location, Binaries.HostFxr.FileName)); - } - // Make a copy of the built .NET, as we will enable test-only behaviour copiedDotnet = TestArtifact.CreateFromCopy(nameof(NativeHostApis), TestContext.BuiltDotNet.BinPath); TestBehaviorEnabledDotNet = new DotNetCli(copiedDotnet.Location); @@ -784,6 +776,14 @@ public SharedTestState() // as we just delete the entire copy after the tests run. _ = TestOnlyProductBehavior.Enable(TestBehaviorEnabledDotNet.GreatestVersionHostFxrFilePath); + HostApiInvokerApp = TestApp.CreateFromBuiltAssets("HostApiInvokerApp"); + + // On non-Windows, we can't just P/Invoke to already loaded hostfxr, so provide the app with + // paths to hostfxr so that it can handle resolving the library. + RuntimeConfig.FromFile(HostApiInvokerApp.RuntimeConfigJson) + .WithProperty("HOSTFXR_PATH", TestContext.BuiltDotNet.GreatestVersionHostFxrFilePath) + .WithProperty("HOSTFXR_PATH_TEST_BEHAVIOR", TestBehaviorEnabledDotNet.GreatestVersionHostFxrFilePath); + SdkAndFrameworkFixture = new SdkAndFrameworkFixture(); }