Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// Opt-out telemetry
Environment.SetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT", "1");

CommandLine.MaxOutstandingCommands = Environment.ProcessorCount;
DotnetCli.DoNotRetry = Debugger.IsAttached;

ITestApplicationBuilder builder = await TestApplication.CreateBuilderAsync(args);
Expand All @@ -29,5 +28,4 @@ CompositeExtensionFactory<SlowestTestsConsumer> slowestTestCompositeServiceFacto
builder.TestHost.AddTestSessionLifetimeHandle(slowestTestCompositeServiceFactory);
using ITestApplication app = await builder.BuildAsync();
int returnValue = await app.RunAsync();
Console.WriteLine($"Process started: {CommandLine.TotalProcessesAttempt}");
return returnValue;
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
// Opt-out telemetry
Environment.SetEnvironmentVariable("DOTNET_CLI_TELEMETRY_OPTOUT", "1");

CommandLine.MaxOutstandingCommands = Environment.ProcessorCount;
DotnetCli.DoNotRetry = Debugger.IsAttached;

ITestApplicationBuilder builder = await TestApplication.CreateBuilderAsync(args);
Expand All @@ -30,5 +29,4 @@ CompositeExtensionFactory<SlowestTestsConsumer> slowestTestCompositeServiceFacto
builder.TestHost.AddTestSessionLifetimeHandle(slowestTestCompositeServiceFactory);
using ITestApplication app = await builder.BuildAsync();
int returnValue = await app.RunAsync();
Console.WriteLine($"Process started: {CommandLine.TotalProcessesAttempt}");
return returnValue;
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected async Task<TestingPlatformClient> StartAsServerAndConnectToTheClientAs
EnvironmentVariables = environmentVariables,
};

IProcessHandle processHandler = ProcessFactory.Start(processConfig, cleanDefaultEnvironmentVariableIfCustomAreProvided: false);
(IProcessHandle processHandler, _) = ProcessFactory.Start(processConfig, cleanDefaultEnvironmentVariableIfCustomAreProvided: false);

TcpClient? tcpClient;
using CancellationTokenSource cancellationTokenSource = new(TimeSpan.FromSeconds(60));
Expand Down
65 changes: 22 additions & 43 deletions test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@

public sealed class CommandLine : IDisposable
{
private static int s_totalProcessesAttempt;
[SuppressMessage("Style", "IDE0032:Use auto property", Justification = "It's causing some runtime issue")]
private static int s_maxOutstandingCommand = Environment.ProcessorCount;
private static SemaphoreSlim s_maxOutstandingCommands_semaphore = new(s_maxOutstandingCommand, s_maxOutstandingCommand);

public static int TotalProcessesAttempt => s_totalProcessesAttempt;

private readonly List<string> _errorOutputLines = [];
private readonly List<string> _standardOutputLines = [];
private IProcessHandle? _process;
Expand All @@ -26,18 +19,6 @@

public string ErrorOutput => string.Join(Environment.NewLine, _errorOutputLines);

public static int MaxOutstandingCommands
{
get => s_maxOutstandingCommand;

set
{
s_maxOutstandingCommand = value;
s_maxOutstandingCommands_semaphore.Dispose();
s_maxOutstandingCommands_semaphore = new SemaphoreSlim(s_maxOutstandingCommand, s_maxOutstandingCommand);
}
}

public async Task RunAsync(
string commandLine,
IDictionary<string, string?>? environmentVariables = null,
Expand All @@ -46,7 +27,7 @@
int exitCode = await RunAsyncAndReturnExitCodeAsync(commandLine, environmentVariables, cancellationToken: cancellationToken);
if (exitCode != 0)
{
throw new InvalidOperationException(

Check failure on line 30 in test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Windows Debug)

test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs#L30

test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs(30,1): error : Test method Microsoft.Testing.Platform.Acceptance.IntegrationTests.MSBuildTests_Test.RunUsingTestTargetWithNetfxMSBuild threw exception: System.InvalidOperationException: Non-zero exit code 1 from command line: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests /t:Restore' STD: MSBuild version 17.14.19+164abd434 for .NET Framework Build started 11/2/2025 9:24:44 PM. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : Could not resolve SDK "Microsoft.NET.Sdk". Exactly one of the probing messages below indicates why we could not resolve the SDK. Investigate and resolve that message to correctly specify the SDK. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : Unable to locate the .NET SDK. Check that it is installed, your PATH is configured for the correct architecture, and that the version specified in global.json (if any) matches the installed version. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : The NuGetSdkResolver did not resolve this SDK because there was no version specified in the project or global.json. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : MSB4276: The default SDK resolver failed to resolve SDK "Microsoft.NET.Sdk" because directory "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Sdks\Microsoft.NET.Sdk\Sdk" did not exist. Project "D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj" on node 1 (Restore target(s)). D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. Done Building Project "D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj" (Restore target(s)) -- FAILED. Build FAILED. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : Could not resolve SDK "Microsoft.NET.Sdk". Exactly one of the probing messages below indicates why we could not resolve the SDK. Investigate and resolve that message to correctly specify the SDK. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : Unable to locate the .NET SDK. Check that it is installed, your PATH is configured for the correct architecture, and that the version specified in global.json (if any) matches the installed version. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : The NuGetSdkResolver did not resolve this SDK because there was no version specified in the project or global.json. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : MSB4276: The default SDK resolver failed to resolve SDK "Microsoft.NET.Sdk" because directory "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Sdks\Microsoft.NET.Sdk\Sdk" did not exist. "D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj" (Restore target) (1) -> D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. 0 Warning(s) 2 Error(s) Time Elapsed 00:00:00.96 ERR: No .NET SDKs were found. Download a .NET SDK: https://aka.ms/dotnet/download Learn about SDK resolution: https://aka.ms/dotnet/sdk-not-found

Check failure on line 30 in test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx (Build Windows Release)

test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs#L30

test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs(30,1): error : Test method Microsoft.Testing.Platform.Acceptance.IntegrationTests.MSBuildTests_Test.RunUsingTestTargetWithNetfxMSBuild threw exception: System.InvalidOperationException: Non-zero exit code 1 from command line: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests /t:Restore' STD: MSBuild version 17.14.19+164abd434 for .NET Framework Build started 11/2/2025 9:26:29 PM. D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error : Could not resolve SDK "Microsoft.NET.Sdk". Exactly one of the probing messages below indicates why we could not resolve the SDK. Investigate and resolve that message to correctly specify the SDK. D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error : Unable to locate the .NET SDK. Check that it is installed, your PATH is configured for the correct architecture, and that the version specified in global.json (if any) matches the installed version. D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error : The NuGetSdkResolver did not resolve this SDK because there was no version specified in the project or global.json. D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error : MSB4276: The default SDK resolver failed to resolve SDK "Microsoft.NET.Sdk" because directory "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Sdks\Microsoft.NET.Sdk\Sdk" did not exist. Project "D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj" on node 1 (Restore target(s)). D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. Done Building Project "D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj" (Restore target(s)) -- FAILED. Build FAILED. D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error : Could not resolve SDK "Microsoft.NET.Sdk". Exactly one of the probing messages below indicates why we could not resolve the SDK. Investigate and resolve that message to correctly specify the SDK. D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error : Unable to locate the .NET SDK. Check that it is installed, your PATH is configured for the correct architecture, and that the version specified in global.json (if any) matches the installed version. D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error : The NuGetSdkResolver did not resolve this SDK because there was no version specified in the project or global.json. D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error : MSB4276: The default SDK resolver failed to resolve SDK "Microsoft.NET.Sdk" because directory "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Sdks\Microsoft.NET.Sdk\Sdk" did not exist. "D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj" (Restore target) (1) -> D:\a\_work\1\s\artifacts\tmp\Release\testsuite\eU8zO\MSBuildTests\MSBuild Tests.csproj : error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. 0 Warning(s) 2 Error(s) Time Elapsed 00:00:00.64 ERR: No .NET SDKs were found. Download a .NET SDK: https://aka.ms/dotnet/download Learn about SDK resolution: https://aka.ms/dotnet/sdk-not-found

Check failure on line 30 in test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs

View check run for this annotation

Azure Pipelines / microsoft.testfx

test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs#L30

test/Utilities/Microsoft.Testing.TestInfrastructure/CommandLine.cs(30,1): error : Test method Microsoft.Testing.Platform.Acceptance.IntegrationTests.MSBuildTests_Test.RunUsingTestTargetWithNetfxMSBuild threw exception: System.InvalidOperationException: Non-zero exit code 1 from command line: '"C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\MSBuild.exe" D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests /t:Restore' STD: MSBuild version 17.14.19+164abd434 for .NET Framework Build started 11/2/2025 9:24:44 PM. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : Could not resolve SDK "Microsoft.NET.Sdk". Exactly one of the probing messages below indicates why we could not resolve the SDK. Investigate and resolve that message to correctly specify the SDK. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : Unable to locate the .NET SDK. Check that it is installed, your PATH is configured for the correct architecture, and that the version specified in global.json (if any) matches the installed version. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : The NuGetSdkResolver did not resolve this SDK because there was no version specified in the project or global.json. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : MSB4276: The default SDK resolver failed to resolve SDK "Microsoft.NET.Sdk" because directory "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Sdks\Microsoft.NET.Sdk\Sdk" did not exist. Project "D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj" on node 1 (Restore target(s)). D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. Done Building Project "D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj" (Restore target(s)) -- FAILED. Build FAILED. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : Could not resolve SDK "Microsoft.NET.Sdk". Exactly one of the probing messages below indicates why we could not resolve the SDK. Investigate and resolve that message to correctly specify the SDK. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : Unable to locate the .NET SDK. Check that it is installed, your PATH is configured for the correct architecture, and that the version specified in global.json (if any) matches the installed version. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : The NuGetSdkResolver did not resolve this SDK because there was no version specified in the project or global.json. D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error : MSB4276: The default SDK resolver failed to resolve SDK "Microsoft.NET.Sdk" because directory "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Sdks\Microsoft.NET.Sdk\Sdk" did not exist. "D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj" (Restore target) (1) -> D:\a\_work\1\s\artifacts\tmp\Debug\testsuite\JA9a7\MSBuildTests\MSBuild Tests.csproj : error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. 0 Warning(s) 2 Error(s) Time Elapsed 00:00:00.96 ERR: No .NET SDKs were found. Download a .NET SDK: https://aka.ms/dotnet/download Learn about SDK resolution: https://aka.ms/dotnet/sdk-not-found
$"""
Non-zero exit code {exitCode} from command line: '{commandLine}'
STD: {StandardOutput}
Expand Down Expand Up @@ -75,30 +56,22 @@
bool cleanDefaultEnvironmentVariableIfCustomAreProvided = false,
CancellationToken cancellationToken = default)
{
await s_maxOutstandingCommands_semaphore.WaitAsync(cancellationToken);
try
(string command, string arguments) = GetCommandAndArguments(commandLine);
_errorOutputLines.Clear();
_standardOutputLines.Clear();
ProcessConfiguration startInfo = new(command)
{
Interlocked.Increment(ref s_totalProcessesAttempt);
(string command, string arguments) = GetCommandAndArguments(commandLine);
_errorOutputLines.Clear();
_standardOutputLines.Clear();
ProcessConfiguration startInfo = new(command)
{
Arguments = arguments,
EnvironmentVariables = environmentVariables,
OnErrorOutput = (_, o) => _errorOutputLines.Add(ClearBOM(o)),
OnStandardOutput = (_, o) => _standardOutputLines.Add(ClearBOM(o)),
WorkingDirectory = workingDirectory,
};
_process = ProcessFactory.Start(startInfo, cleanDefaultEnvironmentVariableIfCustomAreProvided);

using CancellationTokenRegistration registration = cancellationToken.Register(() => _process.Kill());
return await _process.WaitForExitAsync(cancellationToken);
}
finally
{
s_maxOutstandingCommands_semaphore.Release();
}
Arguments = arguments,
EnvironmentVariables = environmentVariables,
OnErrorOutput = (_, o) => _errorOutputLines.Add(ClearBOM(o)),
OnStandardOutput = (_, o) => _standardOutputLines.Add(ClearBOM(o)),
WorkingDirectory = workingDirectory,
};
(_process, Task outputAndErrorTask) = ProcessFactory.Start(startInfo, cleanDefaultEnvironmentVariableIfCustomAreProvided);

using CancellationTokenRegistration registration = cancellationToken.Register(() => _process.Kill());
await outputAndErrorTask;
return await _process.WaitForExitAsync(cancellationToken);
}

/// <summary>
Expand All @@ -113,5 +86,11 @@
return firstChar == byteOrderMark ? outputLine[1..] : outputLine;
}

public void Dispose() => _process?.Kill();
public void Dispose()
{
if (_process?.HasExited == false)
{
_process.Kill();
}
}
}
110 changes: 43 additions & 67 deletions test/Utilities/Microsoft.Testing.TestInfrastructure/DotnetCli.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,6 @@ public static class DotnetCli

private static int s_binlogCounter;

[SuppressMessage("Style", "IDE0032:Use auto property", Justification = "It's causing some runtime bug")]
private static int s_maxOutstandingCommand = Environment.ProcessorCount;
private static SemaphoreSlim s_maxOutstandingCommands_semaphore = new(s_maxOutstandingCommand, s_maxOutstandingCommand);

public static int MaxOutstandingCommands
{
get => s_maxOutstandingCommand;

set
{
s_maxOutstandingCommand = value;
s_maxOutstandingCommands_semaphore.Dispose();
s_maxOutstandingCommands_semaphore = new SemaphoreSlim(s_maxOutstandingCommand, s_maxOutstandingCommand);
}
}

public static bool DoNotRetry { get; set; }

public static async Task<DotnetMuxerResult> RunAsync(
Expand All @@ -61,69 +45,61 @@ public static async Task<DotnetMuxerResult> RunAsync(
[CallerMemberName] string callerMemberName = "",
CancellationToken cancellationToken = default)
{
await s_maxOutstandingCommands_semaphore.WaitAsync(cancellationToken);
try
environmentVariables ??= [];
foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
{
environmentVariables ??= [];
foreach (DictionaryEntry entry in Environment.GetEnvironmentVariables())
// Skip all unwanted environment variables.
string? key = entry.Key.ToString();
if (WellKnownEnvironmentVariables.ToSkipEnvironmentVariables.Contains(key, StringComparer.OrdinalIgnoreCase))
{
// Skip all unwanted environment variables.
string? key = entry.Key.ToString();
if (WellKnownEnvironmentVariables.ToSkipEnvironmentVariables.Contains(key, StringComparer.OrdinalIgnoreCase))
{
continue;
}
continue;
}

if (disableCodeCoverage)
if (disableCodeCoverage)
{
// Disable the code coverage during the build.
if (CodeCoverageEnvironmentVariables.Contains(key, StringComparer.OrdinalIgnoreCase))
{
// Disable the code coverage during the build.
if (CodeCoverageEnvironmentVariables.Contains(key, StringComparer.OrdinalIgnoreCase))
{
continue;
}
continue;
}

// We use TryAdd to let tests "overwrite" existing environment variables.
// Consider that the given dictionary has "TESTINGPLATFORM_UI_LANGUAGE" as a key.
// And also Environment.GetEnvironmentVariables() is returning TESTINGPLATFORM_UI_LANGUAGE.
// In that case, we do a "TryAdd" which effectively means the value from the original dictionary wins.
environmentVariables.TryAdd(key!, entry.Value!.ToString()!);
}

if (disableTelemetry)
{
environmentVariables.Add("DOTNET_CLI_TELEMETRY_OPTOUT", "1");
}
// We use TryAdd to let tests "overwrite" existing environment variables.
// Consider that the given dictionary has "TESTINGPLATFORM_UI_LANGUAGE" as a key.
// And also Environment.GetEnvironmentVariables() is returning TESTINGPLATFORM_UI_LANGUAGE.
// In that case, we do a "TryAdd" which effectively means the value from the original dictionary wins.
environmentVariables.TryAdd(key!, entry.Value!.ToString()!);
}

if (disableTelemetry)
{
environmentVariables.Add("DOTNET_CLI_TELEMETRY_OPTOUT", "1");
}

environmentVariables["NUGET_PACKAGES"] = nugetGlobalPackagesFolder;
environmentVariables["NUGET_PACKAGES"] = nugetGlobalPackagesFolder;

string extraArgs = warnAsError ? " -p:MSBuildTreatWarningsAsErrors=true" : string.Empty;
extraArgs += suppressPreviewDotNetMessage ? " -p:SuppressNETCoreSdkPreviewMessage=true" : string.Empty;
if (args.IndexOf("-- ", StringComparison.Ordinal) is int platformArgsIndex && platformArgsIndex > 0)
{
args = args.Insert(platformArgsIndex, extraArgs + " ");
}
else
{
args += extraArgs;
}
string extraArgs = warnAsError ? " -p:MSBuildTreatWarningsAsErrors=true" : string.Empty;
extraArgs += suppressPreviewDotNetMessage ? " -p:SuppressNETCoreSdkPreviewMessage=true" : string.Empty;
if (args.IndexOf("-- ", StringComparison.Ordinal) is int platformArgsIndex && platformArgsIndex > 0)
{
args = args.Insert(platformArgsIndex, extraArgs + " ");
}
else
{
args += extraArgs;
}

if (DoNotRetry)
{
return await CallTheMuxerAsync(args, environmentVariables, workingDirectory, failIfReturnValueIsNotZero, callerMemberName, cancellationToken);
}
else
{
IEnumerable<TimeSpan> delay = Backoff.ExponentialBackoff(TimeSpan.FromSeconds(3), retryCount, factor: 1.5);
return await Policy
.Handle<Exception>()
.WaitAndRetryAsync(delay)
.ExecuteAsync(async ct => await CallTheMuxerAsync(args, environmentVariables, workingDirectory, failIfReturnValueIsNotZero, callerMemberName, ct), cancellationToken);
}
if (DoNotRetry)
{
return await CallTheMuxerAsync(args, environmentVariables, workingDirectory, failIfReturnValueIsNotZero, callerMemberName, cancellationToken);
}
finally
else
{
s_maxOutstandingCommands_semaphore.Release();
IEnumerable<TimeSpan> delay = Backoff.ExponentialBackoff(TimeSpan.FromSeconds(3), retryCount, factor: 1.5);
return await Policy
.Handle<Exception>()
.WaitAndRetryAsync(delay)
.ExecuteAsync(async ct => await CallTheMuxerAsync(args, environmentVariables, workingDirectory, failIfReturnValueIsNotZero, callerMemberName, ct), cancellationToken);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public interface IProcessHandle

TextReader StandardOutput { get; }

bool HasExited { get; }

void Dispose();

void Kill();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Microsoft.Testing.TestInfrastructure;

public static class ProcessFactory
{
public static IProcessHandle Start(ProcessConfiguration config, bool cleanDefaultEnvironmentVariableIfCustomAreProvided = false)
public static (IProcessHandle Handle, Task OutputAndErrorTask) Start(ProcessConfiguration config, bool cleanDefaultEnvironmentVariableIfCustomAreProvided = false)
{
string fullPath = config.FileName; // Path.GetFullPath(startInfo.FileName);
string workingDirectory = config.WorkingDirectory
Expand Down Expand Up @@ -61,32 +61,34 @@ public static IProcessHandle Start(ProcessConfiguration config, bool cleanDefaul
process.Exited += (s, e) => config.OnExit.Invoke(processHandle, process.ExitCode);
}

if (config.OnStandardOutput != null)
if (!process.Start())
{
process.OutputDataReceived += (s, e) =>
throw new InvalidOperationException("Process failed to start");
}

Task outputTask = Task.Factory.StartNew(
() =>
{
if (!string.IsNullOrWhiteSpace(e.Data))
while (process.StandardOutput.ReadLine() is string line)
{
config.OnStandardOutput(processHandle, e.Data);
if (!string.IsNullOrWhiteSpace(line))
{
config.OnStandardOutput?.Invoke(processHandle, line);
}
}
};
}
}, TaskCreationOptions.LongRunning);

if (config.OnErrorOutput != null)
{
process.ErrorDataReceived += (s, e) =>
Task errorTask = Task.Factory.StartNew(
() =>
{
if (!string.IsNullOrWhiteSpace(e.Data))
while (process.StandardError.ReadLine() is string line)
{
config.OnErrorOutput(processHandle, e.Data);
if (!string.IsNullOrWhiteSpace(line))
{
config.OnErrorOutput?.Invoke(processHandle, line);
}
}
};
}

if (!process.Start())
{
throw new InvalidOperationException("Process failed to start");
}
}, TaskCreationOptions.LongRunning);

try
{
Expand All @@ -100,16 +102,6 @@ public static IProcessHandle Start(ProcessConfiguration config, bool cleanDefaul

processHandleInfo.Id = process.Id;

if (config.OnStandardOutput != null)
{
process.BeginOutputReadLine();
}

if (config.OnErrorOutput != null)
{
process.BeginErrorReadLine();
}

return processHandle;
return (processHandle, Task.WhenAll(outputTask, errorTask));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ internal ProcessHandle(Process process, ProcessHandleInfo processHandleInfo)

public TextReader StandardOutput => _process.StandardOutput;

public bool HasExited => _process.HasExited;

public int ExitCode => _process.ExitCode;

public async Task<int> WaitForExitAsync(CancellationToken cancellationToken = default)
Expand Down
Loading
Loading