84 lines
2.6 KiB
C#
84 lines
2.6 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Microsoft.AspNetCore.WebSockets.ConformanceTest.Autobahn
|
|
{
|
|
public class Executable
|
|
{
|
|
private static readonly string _exeSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty;
|
|
|
|
private readonly string _path;
|
|
|
|
protected Executable(string path)
|
|
{
|
|
_path = path;
|
|
}
|
|
|
|
public static string Locate(string name)
|
|
{
|
|
foreach (var dir in Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator))
|
|
{
|
|
var candidate = Path.Combine(dir, name + _exeSuffix);
|
|
if (File.Exists(candidate))
|
|
{
|
|
return candidate;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public async Task<int> ExecAsync(string args, CancellationToken cancellationToken, ILogger logger)
|
|
{
|
|
var process = new Process()
|
|
{
|
|
StartInfo = new ProcessStartInfo()
|
|
{
|
|
FileName = _path,
|
|
Arguments = args,
|
|
UseShellExecute = false,
|
|
RedirectStandardError = true,
|
|
RedirectStandardOutput = true
|
|
},
|
|
EnableRaisingEvents = true
|
|
};
|
|
var tcs = new TaskCompletionSource<int>();
|
|
|
|
using (cancellationToken.Register(() => Cancel(process, tcs)))
|
|
{
|
|
process.Exited += (_, __) => tcs.TrySetResult(process.ExitCode);
|
|
process.OutputDataReceived += (_, a) => LogIfNotNull(logger.LogInformation, "stdout: {0}", a.Data);
|
|
process.ErrorDataReceived += (_, a) => LogIfNotNull(logger.LogError, "stderr: {0}", a.Data);
|
|
|
|
process.Start();
|
|
|
|
process.BeginErrorReadLine();
|
|
process.BeginOutputReadLine();
|
|
|
|
return await tcs.Task;
|
|
}
|
|
}
|
|
|
|
private void LogIfNotNull(Action<string, object[]> logger, string message, string data)
|
|
{
|
|
if (!string.IsNullOrEmpty(data))
|
|
{
|
|
logger(message, new[] { data });
|
|
}
|
|
}
|
|
|
|
private static void Cancel(Process process, TaskCompletionSource<int> tcs)
|
|
{
|
|
if (process != null && !process.HasExited)
|
|
{
|
|
process.Kill();
|
|
}
|
|
tcs.TrySetCanceled();
|
|
}
|
|
}
|
|
}
|