/// <summary> /// // TODO [C.Groothoff]: summary. /// </summary> /// <param name="wrapperFunction">Just use <see cref="MethodBase.GetCurrentMethod()"/> as value.</param> /// <param name="beforeArguments">Runtime relevant argument parts that should be placed before the <see cref="ProcessFunctionSpecifiedInformation.ProcessArguments"/> part.</param> /// <param name="afterArguments">Runtime relevant argument parts that should be placed after the <see cref="ProcessFunctionSpecifiedInformation.ProcessArguments"/> part.</param> /// <param name="cancellationToken">Token to cancel the process call.</param> /// <returns>The result of the executed process.</returns> protected async Task <string[]> EvaluateWrapperFunction(MethodBase wrapperFunction, string beforeArguments = null, string afterArguments = null, CancellationToken cancellationToken = default) { // Check if the given function is from the class self. Others are not allowed. var derivedType = GetType(); if (wrapperFunction.DeclaringType != derivedType) { throw new InvalidOperationException( $"The function '{nameof(EvaluateWrapperFunction)}' should only called with functions from the class itself!" + $"The class '{derivedType.FullName}' has no function named '{wrapperFunction.Name}'."); } // Check if the given function also contains the needed attribute. var wrapperArguments = (ProcessFunctionSpecifiedInformation)wrapperFunction .GetCustomAttributes(typeof(ProcessFunctionSpecifiedInformation), true) .FirstOrDefault() ?? throw new InvalidOperationException( $"Missing the '{nameof(ProcessFunctionSpecifiedInformation)}' attribute on the given function!"); var processParts = new List <string> { ProcessName }; processParts.AddIfNotNull(beforeArguments); processParts.Add(wrapperArguments.ProcessArguments); processParts.AddIfNotNull(afterArguments); var wholeProcessCall = string.Join(' ', processParts); Log.Verbose("'{WholeCommand}' is the evaluated process call for the function '{WrapperFunctionName}'", wholeProcessCall, wrapperFunction.GetType().FullName); return(await ProcessX.StartAsync(wholeProcessCall).ToTask(cancellationToken)); }
/// <summary> /// Checks if the given process can be started. /// If that's not the case, the program isn't installed or added to the paths. /// </summary> /// <param name="processName">The process name to check!</param> /// <returns></returns> public async Task <bool> IsProcessStartAble(string processName) { if (processName.Contains(" ")) { throw new ArgumentException( $"Spaces means arguments, found some in '{processName}'! We just want the process name!"); } try { var timeoutToken = CreateTimeoutToken(); var processCall = $"{processName} --version"; // TODO [C.Groothoff]: Reusabler way of the "--version" implementation. _ = await ProcessX.StartAsync(processCall).ToTask(timeoutToken); return(true); } catch (OperationCanceledException) { Log.Warning("Starting process '{ProcessName}' was canceled by timeout!", processName); } catch (Exception ex) { Log.Warning("Starting '{ProcessName}' failed. Reason: '{ExceptionReason}!'", processName, ex.Message.Replace(Environment.NewLine, string.Empty)); } return(false); }
static async Task Main(string[] args) { using (var tcs = new CancellationTokenSource(TimeSpan.FromSeconds(1))) { await foreach (var item in ProcessX.StartAsync("dotnet --info").WithCancellation(tcs.Token)) { Console.WriteLine(item); } } }
static async Task Main(string[] args) { var path = @"..\..\..\..\ReturnMessage\ReturnMessage.csproj"; await ProcessX.StartAsync($"dotnet run --project {path} -- str -m foo -c 10").WriteLineAllAsync(); //var bin = await ProcessX.StartReadBinaryAsync($"dotnet run --project {path} -- bin -s 999 -c 10 -w 10"); //// first argument is Process, if you want to know ProcessID, use StandardInput, use it. //var (_, stdOut, stdError) = ProcessX.GetDualAsyncEnumerable("dotnet --foo --bar"); //var consumeStdOut = Task.Run(async () => //{ // await foreach (var item in stdOut) // { // Console.WriteLine("STDOUT: " + item); // } //}); //var errorBuffered = new List<string>(); //var consumeStdError = Task.Run(async () => //{ // await foreach (var item in stdError) // { // Console.WriteLine("STDERROR: " + item); // errorBuffered.Add(item); // } //}); //try //{ // await Task.WhenAll(consumeStdOut, consumeStdError); //} //catch (ProcessErrorException ex) //{ // // stdout iterator throws exception when exitcode is not 0. // Console.WriteLine("ERROR, ExitCode: " + ex.ExitCode); // // ex.ErrorOutput is empty, if you want to use it, buffer yourself. // // Console.WriteLine(string.Join(Environment.NewLine, errorBuffered)); //} //Console.WriteLine(bin.Length); Console.WriteLine(IsInvalidExitCode(0)); AcceptableExitCodes = new[] { 1 }; Console.WriteLine(IsInvalidExitCode(0)); Console.WriteLine(IsInvalidExitCode(1)); AcceptableExitCodes = new[] { 0, 1 }; Console.WriteLine(IsInvalidExitCode(0)); Console.WriteLine(IsInvalidExitCode(1)); }
public async Task StartWorkerAsync(DFrameOptions options, int processCount, IServiceProvider provider, IFailSignal failSignal, CancellationToken cancellationToken) { this.failSignal = failSignal; var location = Assembly.GetEntryAssembly().Location; var cmd = $"dotnet \"{location}\" --worker-flag"; for (int i = 0; i < processCount; i++) { var startProcessTask = ProcessX.StartAsync(cmd); WriteAll(startProcessTask); } }
async Task RunSolver(ISolver solver) { var testDir = Directory.EnumerateDirectories(CheckerRoot, solver.Name, SearchOption.AllDirectories).Single(); try { await foreach (var line in ProcessX.StartAsync( $"python3 generate.py -p {solver.Name}", workingDirectory: CheckerRoot).ConfigureAwait(false)) { Console.WriteLine(line); } } catch (ProcessErrorException e) when(e.ExitCode == 0) { } catch (ProcessErrorException e) { Console.WriteLine($"ProcessErrorException on {solver.Name}: {e.Message}"); throw; } catch (Exception e) { Console.WriteLine($"Exception on {solver.Name}: {e.Message}"); throw; } var inDir = Path.Combine(testDir, "in"); var outDir = Path.Combine(testDir, "out"); var gotDir = Path.Combine(testDir, "got"); Directory.CreateDirectory(gotDir); foreach (var inputFile in Directory.EnumerateFiles(inDir)) { var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(inputFile); using var rfs = new FileStream(inputFile, FileMode.Open, FileAccess.Read); using var wfs = new FileStream(Path.Combine(gotDir, fileNameWithoutExtension + ".got"), FileMode.Create, FileAccess.ReadWrite); var cr = new ConsoleReader(rfs, UTF8NoBom); var cw = new ConsoleWriter(wfs, UTF8NoBom); solver.Solve(cr, cw); cw.Flush(); try { var checkerPath = Path.Combine(testDir, "checker"); var command = string.Join(" ", checkerPath, Path.Combine(inDir, fileNameWithoutExtension + ".in"), Path.Combine(outDir, fileNameWithoutExtension + ".out"), Path.Combine(gotDir, fileNameWithoutExtension + ".got")); Console.WriteLine($"Run: {solver.Name} - {fileNameWithoutExtension}"); await foreach (var line in ProcessX.StartAsync(command, workingDirectory: CheckerRoot).ConfigureAwait(false)) { Console.WriteLine(line); } } catch (ProcessErrorException e) { Console.WriteLine($"ProcessErrorException on {solver.Name}-{fileNameWithoutExtension}: {e.Message}"); if (e.ExitCode != 0) { throw; } } catch (Exception e) { Console.WriteLine($"Exception on {solver.Name}-{fileNameWithoutExtension}: {e.Message}"); throw; } } }
/// <summary> /// 処理を開始します。 /// </summary> /// <param name="prevExitCode">前処理の終了コード</param> /// <returns>標準出力を返す非同期シーケンス</returns> public override ProcessAsyncEnumerable StartAsync(int prevExitCode) { AddPrevExitCode(StartInfo.EnvironmentVariables, prevExitCode); return(ProcessX.StartAsync(StartInfo)); }
/// <summary> /// 処理を開始します。 /// </summary> /// <param name="prevExitCode">前処理の終了コード</param> /// <returns>標準出力を返す非同期シーケンス</returns> public override ProcessAsyncEnumerable StartAsync(int prevExitCode) { IDictionary <string, string> variables = AddPrevExitCode(EnvironmentVariable, prevExitCode); return(ProcessX.StartAsync(CommandLine, WorkingDirectory, variables, Encoding)); }