public static async ValueTask RunProcessAsync()

in src/dotnet/ReSharperPlugin.DotNetDisassembler/JitDisasm/ProcessUtils.cs [12:100]


    public static async ValueTask<ProcessResult> RunProcessAsync(
        string path,
        string args = "",
        Dictionary<string, string> envVars = null,
        string workingDir = null,
        Action<bool, string> outputLogger = null,
        TimeSpan timeout = default,
        CancellationToken cancellationToken = default)
    {
        var logger = new StringBuilder();
        var loggerForErrors = new StringBuilder();
        var loggerLock = new object();
        Process process = null;

        using var timeoutCts = CreateTimeoutCts(timeout, cancellationToken);
        var effectiveToken = timeoutCts?.Token ?? cancellationToken;

        try
        {
            var processStartInfo = new ProcessStartInfo
            {
                FileName = path,
                UseShellExecute = false,
                CreateNoWindow = true,
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                Arguments = args,
            };

            if (workingDir != null)
                processStartInfo.WorkingDirectory = workingDir;

            if (envVars != null)
            {
                foreach (var envVar in envVars)
                    processStartInfo.EnvironmentVariables[envVar.Key] = envVar.Value;
            }

            effectiveToken.ThrowIfCancellationRequested();
            process = Process.Start(processStartInfo);
            effectiveToken.ThrowIfCancellationRequested();

            process!.ErrorDataReceived += (sender, e) =>
            {
                outputLogger?.Invoke(true, e.Data + "\n");
                lock (loggerLock)
                {
                    logger.AppendLine(e.Data);
                    loggerForErrors.AppendLine(e.Data);
                }
            };
            process.OutputDataReceived += (sender, e) =>
            {
                outputLogger?.Invoke(false, e.Data + "\n");
                lock (loggerLock)
                {
                    logger.AppendLine(e.Data);
                }
            };
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();

            await process.WaitForExitAsync(effectiveToken);

            return new ProcessResult { Error = loggerForErrors.ToString().Trim('\r', '\n'), Output = logger.ToString().Trim('\r', '\n') };
        }
        catch (OperationCanceledException)
        {
            return new ProcessResult
            {
                Output = logger.ToString().Trim('\r', '\n'),
                Error = loggerForErrors.ToString().Trim('\r', '\n'),
                IsTimeout = effectiveToken.IsCancellationRequested && !cancellationToken.IsCancellationRequested,
                IsCancelled = true
            };
        }
        catch (Exception e)
        {
            return new ProcessResult
            {
                Error = $"RunProcess failed:{e.Message}.\npath={path}\nargs={args}\nworkingdir={workingDir ?? Environment.CurrentDirectory}\n{loggerForErrors}",
                Exception = e
            };
        }
        finally
        {
            process.KillProccessSafe();
        }
    }