From 24b35827613a3872aa4d0d1e114349e2053c5d2f Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Mon, 27 Apr 2026 18:08:25 +0200 Subject: [PATCH 1/2] Enlighten GenerateTrustInfo for multithreaded mode Add [MSBuildMultiThreadableTask] to both conditional compilation variants. NETFRAMEWORK version: implement IMultiThreadableTask and absolutize BaseManifest and TrustInfoFile paths before file I/O. Non-Framework version: attribute-only (stub that returns false). Fixes #13619 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Tasks/GenerateTrustInfo.cs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/Tasks/GenerateTrustInfo.cs b/src/Tasks/GenerateTrustInfo.cs index 7d76056879b..63ecf55b34f 100644 --- a/src/Tasks/GenerateTrustInfo.cs +++ b/src/Tasks/GenerateTrustInfo.cs @@ -21,8 +21,11 @@ namespace Microsoft.Build.Tasks /// This task generates the application trust from the base manifest /// and the TargetZone and ExcludedPermissions properties. /// - public sealed class GenerateTrustInfo : TaskExtension, IGenerateTrustInfoTaskContract + [MSBuildMultiThreadableTask] + public sealed class GenerateTrustInfo : TaskExtension, IGenerateTrustInfoTaskContract, IMultiThreadableTask { + public TaskEnvironment TaskEnvironment { get; set; } = TaskEnvironment.Fallback; + private const string Custom = "Custom"; public ITaskItem BaseManifest { get; set; } @@ -50,16 +53,20 @@ public override bool Execute() } // Read trust-info from app.manifest - if (BaseManifest != null && FileSystems.Default.FileExists(BaseManifest.ItemSpec)) + if (BaseManifest != null) { - try - { - trustInfo.ReadManifest(BaseManifest.ItemSpec); - } - catch (Exception ex) + AbsolutePath baseManifestPath = TaskEnvironment.GetAbsolutePath(BaseManifest.ItemSpec); + if (FileSystems.Default.FileExists(baseManifestPath)) { - Log.LogErrorWithCodeFromResources("GenerateManifest.ReadInputManifestFailed", BaseManifest.ItemSpec, ex.Message); - return false; + try + { + trustInfo.ReadManifest(baseManifestPath); + } + catch (Exception ex) + { + Log.LogErrorWithCodeFromResources("GenerateManifest.ReadInputManifestFailed", BaseManifest.ItemSpec, ex.Message); + return false; + } } } @@ -99,7 +106,8 @@ public override bool Execute() } // Write trust-info back to a stand-alone trust file - trustInfo.Write(TrustInfoFile.ItemSpec); + AbsolutePath trustInfoFilePath = TaskEnvironment.GetAbsolutePath(TrustInfoFile.ItemSpec); + trustInfo.Write(trustInfoFilePath); return true; } @@ -107,6 +115,7 @@ public override bool Execute() #else + [MSBuildMultiThreadableTask] public sealed class GenerateTrustInfo : TaskRequiresFramework, IGenerateTrustInfoTaskContract { public GenerateTrustInfo() From ceea4bbd682495443fcd3bb289368c4996efb404 Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Mon, 27 Apr 2026 22:04:17 +0200 Subject: [PATCH 2/2] Address GenerateTrustInfo review feedback: guard empty BaseManifest.ItemSpec The previous code path treated a null-or-empty BaseManifest.ItemSpec as 'no file' via File.Exists returning false. Calling TaskEnvironment.GetAbsolutePath on an empty ItemSpec now throws ArgumentException (Sin 6), regressing that behavior. Add an explicit string.IsNullOrEmpty guard to preserve the old silent no-op semantics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/Tasks/GenerateTrustInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tasks/GenerateTrustInfo.cs b/src/Tasks/GenerateTrustInfo.cs index 63ecf55b34f..26167ac27b2 100644 --- a/src/Tasks/GenerateTrustInfo.cs +++ b/src/Tasks/GenerateTrustInfo.cs @@ -53,7 +53,7 @@ public override bool Execute() } // Read trust-info from app.manifest - if (BaseManifest != null) + if (BaseManifest != null && !string.IsNullOrEmpty(BaseManifest.ItemSpec)) { AbsolutePath baseManifestPath = TaskEnvironment.GetAbsolutePath(BaseManifest.ItemSpec); if (FileSystems.Default.FileExists(baseManifestPath))