Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
65 changes: 65 additions & 0 deletions src/Tasks.UnitTests/AxTlbBaseTask_Tests.cs
Comment thread
AlesProkop marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Build.Tasks;
using Microsoft.Build.Utilities;
using Microsoft.Runtime.Hosting;
using Shouldly;
using Xunit;

#nullable disable
Expand Down Expand Up @@ -309,6 +310,70 @@ public void TaskFailsWhenImproperlySigned()
}
}
}

/// <summary>
/// Regression test for the multithreaded task migration: a relative KeyFile must be
/// resolved against the task's project directory (via TaskEnvironment), not the
/// process working directory.
/// </summary>
[Fact]
public void RelativeKeyFile_ResolvedAgainstTaskEnvironmentProjectDirectory()
{
using TestEnvironment env = TestEnvironment.Create();
string projectDir = env.CreateFolder().Path;
string keyFileName = "myKey.key";
string keyFilePath = Path.Combine(projectDir, keyFileName);
File.WriteAllBytes(keyFilePath, new byte[] { 0x01, 0x02, 0x03, 0x04 });

var t = new ResolveComReference.AxImp
{
ActiveXControlName = "FakeControl.ocx",
ToolPath = projectDir,
KeyFile = keyFileName, // relative — must be resolved against projectDir
TaskEnvironment = TaskEnvironment.CreateWithProjectDirectoryAndEnvironment(projectDir),
};

// Process CWD intentionally differs from projectDir. With the multithreaded fix
// the relative KeyFile resolves via TaskEnvironment.ProjectDirectory, so the
// "InvalidKeyFileSpecified" error must not be logged; the task should instead
// proceed and fail because the file is not a valid key pair.
MockEngine e = new MockEngine();
t.BuildEngine = e;
t.Execute().ShouldBeFalse();

Utilities.VerifyLogDoesNotContainErrorFromResource(e, t.Log, "AxTlbBaseTask.InvalidKeyFileSpecified", keyFileName);
Utilities.VerifyLogContainsErrorFromResource(e, t.Log, "AxTlbBaseTask.StrongNameUtils.NoKeyPairInFile", keyFileName);
}

/// <summary>
/// Regression test for the multithreaded task migration: a relative ToolPath must be
/// resolved against the task's project directory (via TaskEnvironment), not the
/// process working directory.
/// </summary>
[Fact]
public void RelativeToolPath_ResolvedAgainstTaskEnvironmentProjectDirectory()
{
using TestEnvironment env = TestEnvironment.Create();
string projectDir = env.CreateFolder().Path;
string toolDirName = "tools";
Directory.CreateDirectory(Path.Combine(projectDir, toolDirName));

var t = new ResolveComReference.AxImp
{
ActiveXControlName = "FakeControl.ocx",
ToolPath = toolDirName, // relative — must be resolved against projectDir
TaskEnvironment = TaskEnvironment.CreateWithProjectDirectoryAndEnvironment(projectDir),
};

// Process CWD intentionally differs from projectDir. With the multithreaded fix
// the relative ToolPath resolves via TaskEnvironment.ProjectDirectory, so the
// "SdkOrToolPathNotSpecifiedOrInvalid" error must not be logged.
MockEngine e = new MockEngine();
t.BuildEngine = e;
t.Execute().ShouldBeFalse(); // task still fails for other reasons (missing tool exe)

Utilities.VerifyLogDoesNotContainErrorFromResource(e, t.Log, "AxTlbBaseTask.SdkOrToolPathNotSpecifiedOrInvalid", t.SdkToolsPath ?? "", t.ToolPath ?? "");
}
}

internal sealed class Utilities
Expand Down
3 changes: 3 additions & 0 deletions src/Tasks/AxImp.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 All @@ -16,6 +18,7 @@ public sealed partial class ResolveComReference
/// Defines the "AxImp" MSBuild task, which enables using AxImp.exe
/// to generate Windows Forms wrappers for ActiveX controls.
/// </summary>
[MSBuildMultiThreadableTask]
internal class AxImp : AxTlbBaseTask
{
#region Properties
Expand Down
22 changes: 16 additions & 6 deletions src/Tasks/AxTlbBaseTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Reflection;
using Microsoft.Build.Framework;
using Microsoft.Build.Shared.FileSystem;

#nullable disable
Expand Down Expand Up @@ -107,14 +108,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 +128,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) || !TaskEnvironment.DirectoryExists(ToolPath, Log)) &&
(string.IsNullOrEmpty(SdkToolsPath) || !TaskEnvironment.DirectoryExists(SdkToolsPath, Log)))
{
Log.LogErrorWithCodeFromResources("AxTlbBaseTask.SdkOrToolPathNotSpecifiedOrInvalid", SdkToolsPath ?? "", ToolPath ?? "");
return false;
Expand Down Expand Up @@ -155,6 +158,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
// 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 @@ -175,12 +181,16 @@ private void AddStrongNameOptions(CommandLineBuilderExtension commandLine)
private bool ValidateStrongNameParameters()
{
bool keyFileExists = false;
AbsolutePath keyFileForRead = default;

// Make sure that if KeyFile is defined, it's a real file.
if (!String.IsNullOrEmpty(KeyFile))
{
if (FileSystems.Default.FileExists(KeyFile))
AbsolutePath absolutePathFromKeyFile = TaskEnvironment.GetAbsolutePath(KeyFile);

if (FileSystems.Default.FileExists(absolutePathFromKeyFile))
{
keyFileForRead = absolutePathFromKeyFile;
keyFileExists = true;
}
else
Expand Down Expand Up @@ -216,7 +226,7 @@ private bool ValidateStrongNameParameters()

try
{
StrongNameUtils.GetStrongNameKey(Log, KeyFile, KeyContainer, out keyPair, out publicKey);
StrongNameUtils.GetStrongNameKey(Log, keyFileForRead, KeyContainer, out keyPair, out publicKey);
}
catch (StrongNameException e)
{
Expand Down
3 changes: 3 additions & 0 deletions src/Tasks/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@
<data name="General.FailedToCanonicalizePath">
<value>Could not normalize path "{0}" by resolving "." and ".." segments: {1}. The path will be used as-is.</value>
</data>
<data name="General.FailedToAbsolutizePath">
<value>Could not convert path "{0}" to an absolute path: {1}. The path will be treated as invalid.</value>
</data>
<data name="General.FrameworksFileNotFound">
<value>MSB3082: Task failed because "{0}" was not found, or the .NET Framework {1} is not installed. Please install the .NET Framework {1}.</value>
<comment>{StrBegin="MSB3082: "}</comment>
Expand Down
5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.pl.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.pt-BR.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.ru.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.tr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.zh-Hans.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Tasks/Resources/xlf/Strings.zh-Hant.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading