Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/Tasks.UnitTests/TlbImp_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ public void ReferenceFiles()
t.ReferenceFiles = new string[] { "File1.dll", "File2.dll" };
CommandLine.ValidateHasParameter(
t,
"/reference:File1.dll",
"/reference:" + Path.GetFullPath("File1.dll"),
false /* no response file */);
CommandLine.ValidateHasParameter(
t,
"/reference:File2.dll",
"/reference:" + Path.GetFullPath("File2.dll"),
false /* no response file */);
Comment thread
AlesProkop marked this conversation as resolved.
}
/// <summary>
Expand All @@ -61,7 +61,7 @@ public void TypeLibName()

t.TypeLibName = testParameterValue;
Assert.Equal(testParameterValue, t.TypeLibName); // "New TypeLibName value should be set"
CommandLine.ValidateHasParameter(t, testParameterValue, false /* no response file */);
CommandLine.ValidateHasParameter(t, Path.GetFullPath(testParameterValue), false /* no response file */);
}

/// <summary>
Expand Down Expand Up @@ -167,7 +167,7 @@ public void OutputAssembly()
Assert.Equal(testParameterValue, t.OutputAssembly); // "New OutputAssembly value should be set"
CommandLine.ValidateHasParameter(
t,
@"/out:" + testParameterValue,
@"/out:" + Path.GetFullPath(testParameterValue),
false /* no response file */);
}

Expand Down
4 changes: 4 additions & 0 deletions src/Tasks/AxReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo)

var axImp = new ResolveComReference.AxImp();

// Propagate TaskEnvironment so the nested ToolTask resolves relative paths against the
// project directory when ResolveComReference itself runs under multithreaded execution.
axImp.TaskEnvironment = TaskEnvironment;

if (ReferenceInfo != null)
{
axImp.ActiveXControlName = ReferenceInfo.strippedTypeLibPath;
Expand Down
7 changes: 7 additions & 0 deletions src/Tasks/AxTlbBaseReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ internal AxTlbBaseReference(TaskLoggingHelper taskLoggingHelper, bool silent, IC
/// </summary>
protected bool IncludeTypeLibVersionInName { get; set; }

/// <summary>
/// The <see cref="TaskEnvironment"/> propagated from the parent <c>ResolveComReference</c> task so that nested
/// <c>TlbImp</c>/<c>AxImp</c> ToolTask invocations resolve relative paths against the project directory
/// (rather than the process current directory) when running under multithreaded execution.
/// </summary>
internal TaskEnvironment TaskEnvironment { get; set; } = TaskEnvironment.Fallback;

#endregion

#region Methods
Expand Down
18 changes: 12 additions & 6 deletions src/Tasks/AxTlbBaseTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,16 @@ protected internal override void AddCommandLineCommands(CommandLineBuilderExtens
protected override string GenerateFullPathToTool()
{
string pathToTool = SdkToolsPathUtility.GeneratePathToTool(
Comment thread
AlesProkop marked this conversation as resolved.
SdkToolsPathUtility.FileInfoExists,
f => !string.IsNullOrEmpty(f)
? SdkToolsPathUtility.FileInfoExists(TaskEnvironment.GetAbsolutePath(f))
: SdkToolsPathUtility.FileInfoExists(f),
Utilities.ProcessorArchitecture.CurrentProcessArchitecture,
SdkToolsPath,
ToolName,
Log,
true);

return pathToTool;
return string.IsNullOrEmpty(pathToTool) ? pathToTool : TaskEnvironment.GetAbsolutePath(pathToTool).Value;
}

/// <summary>
Expand All @@ -125,8 +127,8 @@ protected override bool ValidateParameters()
{
// Verify that a path for the tool exists -- if the tool doesn't exist in it
// we'll worry about that later
if ((String.IsNullOrEmpty(ToolPath) || !FileSystems.Default.DirectoryExists(ToolPath)) &&
(String.IsNullOrEmpty(SdkToolsPath) || !FileSystems.Default.DirectoryExists(SdkToolsPath)))
if ((string.IsNullOrEmpty(ToolPath) || !FileSystems.Default.DirectoryExists(TaskEnvironment.GetAbsolutePath(ToolPath))) &&
(string.IsNullOrEmpty(SdkToolsPath) || !FileSystems.Default.DirectoryExists(TaskEnvironment.GetAbsolutePath(SdkToolsPath))))
{
Log.LogErrorWithCodeFromResources("AxTlbBaseTask.SdkOrToolPathNotSpecifiedOrInvalid", SdkToolsPath ?? "", ToolPath ?? "");
return false;
Expand Down Expand Up @@ -155,6 +157,9 @@ private void AddStrongNameOptions(CommandLineBuilderExtension commandLine)
// throw an error.
//
// So use /publickey if that's all our KeyFile contains, but KeyFile otherwise.
// The KeyFile path is passed verbatim to the spawned tool; ToolTask sets the child
Comment thread
AlesProkop marked this conversation as resolved.
Outdated
// process's WorkingDirectory to the project directory (via TaskEnvironment), so the
// tool resolves relative paths correctly without us absolutizing here.
if (_delaySigningAndKeyFileOnlyContainsPublicKey)
{
commandLine.AppendSwitchIfNotNull("/publickey:", KeyFile);
Expand All @@ -179,7 +184,7 @@ private bool ValidateStrongNameParameters()
// Make sure that if KeyFile is defined, it's a real file.
if (!String.IsNullOrEmpty(KeyFile))
{
if (FileSystems.Default.FileExists(KeyFile))
if (FileSystems.Default.FileExists(TaskEnvironment.GetAbsolutePath(KeyFile)))
{
keyFileExists = true;
}
Expand Down Expand Up @@ -216,7 +221,8 @@ private bool ValidateStrongNameParameters()

try
{
StrongNameUtils.GetStrongNameKey(Log, KeyFile, KeyContainer, out keyPair, out publicKey);
string keyFileForRead = string.IsNullOrEmpty(KeyFile) ? KeyFile : TaskEnvironment.GetAbsolutePath(KeyFile).Value;
StrongNameUtils.GetStrongNameKey(Log, keyFileForRead, KeyContainer, out keyPair, out publicKey);
}
catch (StrongNameException e)
{
Expand Down
7 changes: 6 additions & 1 deletion src/Tasks/ResolveComReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,11 +197,14 @@ public ResolveComReference()
/// <summary>
/// Main class for the COM reference resolution task
/// </summary>
public sealed partial class ResolveComReference : AppDomainIsolatedTaskExtension, IResolveComReferenceTaskContract, IComReferenceResolver
public sealed partial class ResolveComReference : AppDomainIsolatedTaskExtension, IResolveComReferenceTaskContract, IComReferenceResolver, IMultiThreadableTask
{
#pragma warning disable format // region formatting is different in net7.0 and net472, and cannot be fixed for both
#region Properties

/// <inheritdoc />
public TaskEnvironment TaskEnvironment { get; set; } = TaskEnvironment.Fallback;

public ITaskItem[] TypeLibNames { get; set; }

public ITaskItem[] TypeLibFiles { get; set; }
Expand Down Expand Up @@ -1356,6 +1359,7 @@ internal bool ResolveComReferenceTlb(ComReferenceInfo referenceInfo, string outp
outputDirectory, isTemporary, DelaySign, KeyFile, KeyContainer, NoClassMembers,
TargetProcessorArchitecture, IncludeVersionInInteropName, ExecuteAsTool, _tlbimpPath,
BuildEngine, EnvironmentVariables);
reference.TaskEnvironment = TaskEnvironment;

// wrapper doesn't exist or needs regeneration? generate it then
if (!reference.FindExistingWrapper(out wrapperInfo, _timestampCache[referenceInfo.strippedTypeLibPath]))
Expand Down Expand Up @@ -1400,6 +1404,7 @@ internal bool ResolveComReferenceAx(ComReferenceInfo referenceInfo, string outpu
// not in the cache? see if anyone was kind enough to generate it for us

var reference = new AxReference(Log, Silent, this, referenceInfo, refName, outputDirectory, DelaySign, KeyFile, KeyContainer, IncludeVersionInInteropName, _aximpPath, BuildEngine, EnvironmentVariables);
reference.TaskEnvironment = TaskEnvironment;

// wrapper doesn't exist or needs regeneration? generate it then
if (!reference.FindExistingWrapper(out wrapperInfo, _timestampCache[referenceInfo.strippedTypeLibPath]))
Expand Down
17 changes: 14 additions & 3 deletions src/Tasks/TlbImp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System;

using Microsoft.Build.Framework;

#nullable disable

namespace Microsoft.Build.Tasks
Expand Down Expand Up @@ -40,6 +42,7 @@ internal enum TlbImpTransformFlags
/// Defines the "TlbImp" MSBuild task, which enables using TlbImp.exe
/// to generate assemblies from type libraries.
/// </summary>
[MSBuildMultiThreadableTask]
internal class TlbImp : AxTlbBaseTask
{
#region Properties
Expand Down Expand Up @@ -236,15 +239,15 @@ public string[] ReferenceFiles
protected internal override void AddCommandLineCommands(CommandLineBuilderExtension commandLine)
{
// .ocx file being imported
commandLine.AppendFileNameIfNotNull(TypeLibName);
commandLine.AppendFileNameIfNotNull(AbsolutizeIfNotEmpty(TypeLibName));
Comment thread
AlesProkop marked this conversation as resolved.
Outdated

// options
Comment thread
AlesProkop marked this conversation as resolved.
commandLine.AppendSwitchIfNotNull("/asmversion:", AssemblyVersion?.ToString());
commandLine.AppendSwitchIfNotNull("/namespace:", AssemblyNamespace);
commandLine.AppendSwitchIfNotNull("/machine:", Machine);
commandLine.AppendWhenTrue("/noclassmembers", Bag, "PreventClassMembers");
commandLine.AppendWhenTrue("/nologo", Bag, "NoLogo");
commandLine.AppendSwitchIfNotNull("/out:", OutputAssembly);
commandLine.AppendSwitchIfNotNull("/out:", AbsolutizeIfNotEmpty(OutputAssembly));
commandLine.AppendWhenTrue("/silent", Bag, "Silent");
commandLine.AppendWhenTrue("/sysarray", Bag, "SafeArrayAsSystemArray");
commandLine.AppendSwitchIfNotNull("/transform:", ConvertTransformFlagsToCommandLineCommand(Transform));
Expand All @@ -253,13 +256,21 @@ protected internal override void AddCommandLineCommands(CommandLineBuilderExtens
{
foreach (var referenceFile in ReferenceFiles)
{
commandLine.AppendSwitchIfNotNull("/reference:", referenceFile);
commandLine.AppendSwitchIfNotNull("/reference:", AbsolutizeIfNotEmpty(referenceFile));
}
}

base.AddCommandLineCommands(commandLine);
}

/// <summary>
/// Returns the absolutized form of <paramref name="path"/> when it is non-empty,
/// or the original value when null/empty (preserves prior null/empty handling of
/// the CommandLineBuilderExtension Append*IfNotNull helpers).
/// </summary>
private string AbsolutizeIfNotEmpty(string path)
=> string.IsNullOrEmpty(path) ? path : TaskEnvironment.GetAbsolutePath(path).Value;

/// <summary>
/// Validates the parameters passed to the task
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Tasks/TlbReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo)
Transform = ResolveComReference.TlbImpTransformFlags.TransformDispRetVals
};

// Propagate TaskEnvironment so the nested ToolTask resolves relative paths against the
// project directory when ResolveComReference itself runs under multithreaded execution.
tlbImp.TaskEnvironment = TaskEnvironment;

if (_referenceFiles != null)
{
// Issue is that there may be reference dependencies that need to be passed in. It is possible
Expand Down