Do not print anything to stderr running SCD app without deps.json (#69314)
authorVitek Karas <10670590+vitek-karas@users.noreply.github.com>
Wed, 18 May 2022 11:07:16 +0000 (04:07 -0700)
committerGitHub <noreply@github.com>
Wed, 18 May 2022 11:07:16 +0000 (04:07 -0700)
When we're running self-contained app the `hostfxr` tries to figure out the location of `hostpolicy.dll`. This is done also by looking into the `.deps.json` for the app (which should have a record for `hostpolicy.dll` in it). If the file is missing the code will move on and find the `hostpolicy.dll` in the app's folder, but it will also print out a message to stderr.

This means that running such app will actually work, but the host outputs a message to stderr - effectively "corrupting" the app's own output.

Note that this doesn't affects framework dependent apps without `.deps.json` since they look into the framework's `.deps.json` for `hostpolicy.dll`.

src/installer/tests/HostActivation.Tests/StandaloneAppActivation.cs
src/native/corehost/fxr/standalone/hostpolicy_resolver.cpp

index cc561c6..710916e 100644 (file)
@@ -59,6 +59,26 @@ namespace HostActivation.Tests
         }
 
         [Fact]
+        public void Running_Publish_Output_Standalone_EXE_with_no_DepsJson_and_no_RuntimeConfig_Local_Succeeds()
+        {
+            var fixture = sharedTestState.StandaloneAppFixture_Published
+                .Copy();
+
+            var appExe = fixture.TestProject.AppExe;
+            File.Delete(fixture.TestProject.RuntimeConfigJson);
+            File.Delete(fixture.TestProject.DepsJson);
+
+            Command.Create(appExe)
+                .CaptureStdErr()
+                .CaptureStdOut()
+                .Execute()
+                .Should().Pass()
+                // Note that this is an exact match - we don't expect any output from the host itself
+                .And.HaveStdOut($"Hello World!{Environment.NewLine}{Environment.NewLine}.NET {sharedTestState.RepoDirectories.MicrosoftNETCoreAppVersion}{Environment.NewLine}")
+                .And.NotHaveStdErr();
+        }
+
+        [Fact]
         public void Running_Publish_Output_Standalone_EXE_with_Unbound_AppHost_Fails()
         {
             var fixture = sharedTestState.StandaloneAppFixture_Published
index e735e2e..67ddd18 100644 (file)
@@ -242,17 +242,21 @@ bool hostpolicy_resolver::try_get_dir(
     pal::string_t resolved_deps = get_deps_file(is_framework_dependent, app_candidate, specified_deps_file, fx_definitions);
 
     // Resolve hostpolicy version out of the deps file.
-    pal::string_t version = resolve_hostpolicy_version_from_deps(resolved_deps);
-    if (trace::is_enabled() && version.empty() && pal::file_exists(resolved_deps))
+    pal::string_t version;
+    if (pal::file_exists(resolved_deps))
     {
-        trace::warning(_X("Dependency manifest %s does not contain an entry for %s"),
-            resolved_deps.c_str(), _STRINGIFY(HOST_POLICY_PKG_NAME));
-    }
+        version = resolve_hostpolicy_version_from_deps(resolved_deps);
+        if (trace::is_enabled() && version.empty())
+        {
+            trace::warning(_X("Dependency manifest %s does not contain an entry for %s"),
+                resolved_deps.c_str(), _STRINGIFY(HOST_POLICY_PKG_NAME));
+        }
 
-    // Check if the given version of the hostpolicy exists in servicing.
-    if (hostpolicy_exists_in_svc(version, impl_dir))
-    {
-        return true;
+        // Check if the given version of the hostpolicy exists in servicing.
+        if (hostpolicy_exists_in_svc(version, impl_dir))
+        {
+            return true;
+        }
     }
 
     // Get the expected directory that would contain hostpolicy.