Example #1
0
        /// <inheritdoc />
        protected override async Task <Result <Unit, IError> > Run(
            IStateMonad stateMonad,
            CancellationToken cancellationToken)
        {
            var r = await Value.Run(stateMonad, cancellationToken);

            if (r.IsFailure)
            {
                return(r.ConvertFailure <Unit>());
            }

            var stringToPrint = await SerializationMethods.GetStringAsync(r.Value);

            stateMonad.Log(LogLevel.Information, stringToPrint, this);

            return(Unit.Default);
        }
Example #2
0
        /// <inheritdoc />
        public async Task <Result <Unit, IErrorBuilder> > RunExternalProcess(
            string processPath,
            IErrorHandler errorHandler,
            IEnumerable <string> arguments,
            IReadOnlyDictionary <string, string> environmentVariables,
            Encoding encoding,
            IStateMonad stateMonad,
            IStep?callingStep,
            CancellationToken cancellationToken)
        {
            var absolutePath = GetAbsolutePath(processPath);

            if (absolutePath.IsFailure)
            {
                return(absolutePath.ConvertFailure <Unit>());
            }

            var argumentString = string.Join(' ', arguments.Select(EncodeParameterArgument));

            LogSituation.ExternalProcessStarted.Log(
                stateMonad,
                callingStep,
                absolutePath.Value,
                argumentString
                );

            using var pProcess = new Process
                  {
                      StartInfo =
                      {
                          FileName               = absolutePath.Value,
                          Arguments              = argumentString,
                          UseShellExecute        = false,
                          RedirectStandardOutput = true,
                          RedirectStandardError  = true,
                          WindowStyle            = ProcessWindowStyle.Hidden, //don't display a window
                          CreateNoWindow         = true,
                          StandardErrorEncoding  = encoding,
                          StandardOutputEncoding = encoding
                      }
                  };

            foreach (var(key, value) in environmentVariables)
            {
                pProcess.StartInfo.EnvironmentVariables.Add(
                    key,
                    value
                    );
            }

            foreach (var(key, value) in pProcess.StartInfo.Environment)
            {
                LogSituation.EnvironmentVariable.Log(stateMonad, callingStep, key, value);
            }

            var errors = new List <IErrorBuilder>();

            try
            {
                pProcess.Start();

                var channelReader =
                    StreamChannelHelper.ToChannelReader(
                        (pProcess.StandardOutput, StreamSource.Output),
                        (pProcess.StandardError, StreamSource.Error)
                        );

                await foreach (var(line, streamSource) in channelReader.ReadAllAsync(cancellationToken)
                               )
                {
                    if (streamSource == StreamSource.Error)
                    {
                        var errorText = string.IsNullOrWhiteSpace(line) ? "Unknown Error" : line;

                        if (errorHandler.ShouldIgnoreError(errorText))
                        {
                            stateMonad.Log(LogLevel.Warning, line, callingStep);
                        }
                        else
                        {
                            errors.Add(new ErrorBuilder(ErrorCode.ExternalProcessError, errorText));
                        }
                    }
                    else
                    {
                        stateMonad.Log(LogLevel.Information, line, callingStep);
                    }
                }

                // ReSharper disable once MethodHasAsyncOverloadWithCancellation - run on a separate thread
                pProcess.WaitForExit();
            }
        #pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception e)
            {
                errors.Add(new ErrorBuilder(e, ErrorCode.ExternalProcessError));
            }
        #pragma warning restore CA1031 // Do not catch general exception types

            if (errors.Any())
            {
                var e = ErrorBuilderList.Combine(errors);
                return(Result.Failure <Unit, IErrorBuilder>(e));
            }

            return(Unit.Default);
        }