예제 #1
0
        public static async Task <EasyExecResult> ExecAsync(string cmdName, string?arguments = null, string?currentDirectory = null,
                                                            ExecFlags flags          = ExecFlags.Default | ExecFlags.EasyInputOutputMode,
                                                            int easyOutputMaxSize    = Consts.Numbers.DefaultLargeBufferSize, string?easyInputStr = null, int?timeout = null,
                                                            CancellationToken cancel = default, bool debug = false, bool throwOnErrorExitCode = true, string printTag = "",
                                                            Func <string, Task <bool> >?easyOneLineRecvCallbackAsync = null,
                                                            Func <ReadOnlyMemory <byte>, ReadOnlyMemory <byte>, Task <bool> >?easyRealtimeRecvBufCallbackAsync = null,
                                                            int easyRealtimeRecvBufCallbackDelayTickMsecs = 0, StrDictionary <string>?additionalEnvVars = null)
        {
            if (timeout <= 0)
            {
                timeout = Timeout.Infinite;
            }

            ExecOptions opt = new ExecOptions(cmdName, arguments, currentDirectory, flags, easyOutputMaxSize, easyInputStr, printTag,
                                              easyOneLineRecvCallbackAsync, easyRealtimeRecvBufCallbackAsync, easyRealtimeRecvBufCallbackDelayTickMsecs, additionalEnvVars);

            if (debug)
            {
                Dbg.WriteLine($"ExecAsync: --- Starting process \"{cmdName}{(arguments._IsFilled() ? " " : "")}{arguments}\" ---");
            }

            EasyExecResult result;

            try
            {
                using ExecInstance exec = new ExecInstance(opt);

                try
                {
                    await exec.WaitForExitAsync(timeout._NormalizeTimeout(CoresConfig.Timeouts.DefaultEasyExecTimeout), cancel);
                }
                finally
                {
                    await exec.CancelAsync();
                }

                result = new EasyExecResult(exec);
            }
            catch (Exception ex)
            {
                Dbg.WriteLine($"Error on starting process \"{cmdName}{(arguments._IsFilled() ? " " : "")}{arguments}\". Exception: {ex.Message}");
                throw;
            }

            if (debug)
            {
                Dbg.WriteLine($"ExecAsync: The result of process \"{cmdName}{(arguments._IsFilled() ? " " : "")}{arguments}\": " + result.ToString(Str.GetCrlfStr(), false));
            }

            if (throwOnErrorExitCode)
            {
                result.ThrowExceptionIfError();
            }

            return(result);
        }
예제 #2
0
        public static async Task <EasyExecResult> ExecBashAsync(string command, string?currentDirectory = null, ExecFlags flags = ExecFlags.Default | ExecFlags.EasyInputOutputMode,
                                                                int easyOutputMaxSize    = Consts.Numbers.DefaultLargeBufferSize, string?easyInputStr = null, int?timeout = null,
                                                                CancellationToken cancel = default, bool debug = false, bool throwOnErrorExitCode = true)
        {
            if (timeout <= 0)
            {
                timeout = Timeout.Infinite;
            }

            List <string> args = new List <string>();

            args.Add("-c");
            args.Add(command);

            ExecOptions opt = new ExecOptions(Consts.LinuxCommands.Bash, args, currentDirectory, flags, easyOutputMaxSize, easyInputStr);

            if (debug)
            {
                Dbg.WriteLine($"ExecBashAsync: --- Starting bash command \"{command}\" ---");
            }

            EasyExecResult result;

            try
            {
                using ExecInstance exec = new ExecInstance(opt);

                try
                {
                    await exec.WaitForExitAsync(timeout._NormalizeTimeout(CoresConfig.Timeouts.DefaultEasyExecTimeout), cancel);
                }
                finally
                {
                    exec.Cancel();
                }

                result = new EasyExecResult(exec);
            }
            catch (Exception ex)
            {
                Dbg.WriteLine($"Error on bash process \"{command}\". Exception: {ex.Message}");
                throw;
            }

            if (debug)
            {
                Dbg.WriteLine($"ExecAsync: The result of bash \"{command}\": " + result.ToString(Str.GetCrlfStr(), false));
            }

            if (throwOnErrorExitCode)
            {
                result.ThrowExceptionIfError();
            }

            return(result);
        }
예제 #3
0
        public static async Task <EasyExecResult> ExecAsync(string fileName, string?arguments = null, string?currentDirectory = null, ExecFlags flags = ExecFlags.Default | ExecFlags.EasyInputOutputMode,
                                                            int easyOutputMaxSize             = Consts.Numbers.DefaultLargeBufferSize, string?easyInputStr = null, int?timeout = null,
                                                            CancellationToken cancel          = default, bool debug = false, bool throwOnErrorExitCode = true)
        {
            if (timeout <= 0)
            {
                timeout = Timeout.Infinite;
            }

            ExecOptions opt = new ExecOptions(fileName, arguments, currentDirectory, flags, easyOutputMaxSize, easyInputStr);

            if (debug)
            {
                Dbg.WriteLine($"ExecAsync: --- Starting process \"{fileName}{(arguments._IsFilled() ? " " : "")}{arguments}\" ---");
            }

            EasyExecResult result;

            try
            {
                using ExecInstance exec = new ExecInstance(opt);

                try
                {
                    await exec.WaitForExitAsync(timeout._NormalizeTimeout(CoresConfig.Timeouts.DefaultEasyExecTimeout), cancel);
                }
                finally
                {
                    exec.Cancel();
                }

                result = new EasyExecResult(exec);
            }
            catch (Exception ex)
            {
                Dbg.WriteLine($"Error on starting process \"{fileName}{(arguments._IsFilled() ? " " : "")}{arguments}\". Exception: {ex.Message}");
                throw;
            }

            if (debug)
            {
                Dbg.WriteLine($"ExecAsync: The result of process \"{fileName}{(arguments._IsFilled() ? " " : "")}{arguments}\": " + result.ToString(Str.GetCrlfStr(), false));
            }

            if (throwOnErrorExitCode)
            {
                result.ThrowExceptionIfError();
            }

            return(result);
        }
예제 #4
0
        public ExecInstance(ExecOptions options)
        {
            try
            {
                this.InputEncoding  = Console.OutputEncoding;
                this.OutputEncoding = this.ErrorEncoding = Console.InputEncoding;

                this.Options = options._NullCheck();

                ProcessStartInfo info = new ProcessStartInfo()
                {
                    FileName               = options.FileName,
                    UseShellExecute        = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true,
                    RedirectStandardInput  = true,
                    CreateNoWindow         = true,
                    WorkingDirectory       = options.CurrentDirectory._NullIfEmpty() !,
                };

                if (this.Options.AdditionalEnvVars != null)
                {
                    foreach (var kv in this.Options.AdditionalEnvVars)
                    {
                        if (kv.Key._IsFilled() && kv.Value._IsFilled())
                        {
                            info.EnvironmentVariables.Add(kv.Key, kv.Value);
                        }
                    }
                }

                if (options.ArgumentsList != null)
                {
                    options.ArgumentsList._DoForEach(a => info.ArgumentList.Add(a._NonNull()));
                }
                else
                {
                    info.Arguments = options.Arguments._NullIfZeroLen() !;
                }

                StartTick = Time.HighResTick64;

                Proc = Process.Start(info) !;

                Proc._FixProcessObjectHandleLeak(); // メモリリーク解消

                this.ProcessId = Proc.Id;

                // 標準入出力を接続する
                this.StandardPipePoint_MySide = PipePoint.NewDuplexPipeAndGetOneSide(PipePointSide.A_LowerSide);
                this._InputOutputPipePoint    = this.StandardPipePoint_MySide.CounterPart._NullCheck();
                this.StandardPipeWrapper      = new PipePointStreamWrapper(StandardPipePoint_MySide, Proc.StandardOutput.BaseStream, Proc.StandardInput.BaseStream);

                // 標準エラー出力を接続する
                this.ErrorPipePoint_MySide = PipePoint.NewDuplexPipeAndGetOneSide(PipePointSide.A_LowerSide);
                this._ErrorPipePoint       = this.ErrorPipePoint_MySide.CounterPart._NullCheck();
                this.ErrorPipeWrapper      = new PipePointStreamWrapper(ErrorPipePoint_MySide, Proc.StandardError.BaseStream, Stream.Null);

                if (options.Flags.Bit(ExecFlags.EasyInputOutputMode))
                {
                    this.EasyInputOutputStub   = this._InputOutputPipePoint.GetNetAppProtocolStub(noCheckDisconnected: true);
                    this.EasyInputOutputStream = this.EasyInputOutputStub.GetStream();

                    this.EasyErrorStub   = this._ErrorPipePoint.GetNetAppProtocolStub(noCheckDisconnected: true);
                    this.EasyErrorStream = this.EasyErrorStub.GetStream();

                    if (options.EasyInputStr != null && options.EasyInputStr.Length >= 1)
                    {
                        // 標準入力の注入タスク
                        this.EasyInputTask = this.EasyInputOutputStream.SendAsync(this.Options.EasyInputStr !._GetBytes(this.InputEncoding), this.GrandCancel)._LeakCheck();
                    }

                    // 標準出力の読み出しタスク
                    this.EasyOutputTask = this.EasyInputOutputStream._ReadWithMaxBufferSizeAsync(this.Options.EasyOutputMaxSize, this.GrandCancel,
                                                                                                 async(data, cancel) => await EasyPrintRealTimeRecvDataCallbackAsync(data, false, cancel))._LeakCheck();

                    // 標準エラー出力の読み出しタスク
                    this.EasyErrorTask = this.EasyErrorStream._ReadWithMaxBufferSizeAsync(this.Options.EasyOutputMaxSize, this.GrandCancel,
                                                                                          async(data, cancel) => await EasyPrintRealTimeRecvDataCallbackAsync(data, true, cancel))._LeakCheck();

                    // リアルタイムバッファ監視タスク
                    if (Options.EasyRealtimeRecvBufCallbackAsync != null)
                    {
                        this.EasyRealtimeBufferMainteTask = EasyRealtimeBufferMainteTaskAsync(this.GrandCancel)._LeakCheck();
                    }
                }

                this.StartMainLoop(MainLoopAsync);
            }
            catch
            {
                this._DisposeSafe();
                throw;
            }
        }
예제 #5
0
        public ExecInstance(ExecOptions options)
        {
            try
            {
                this.InputEncoding  = Console.OutputEncoding;
                this.OutputEncoding = this.ErrorEncoding = Console.InputEncoding;

                this.Options = options._NullCheck();

                ProcessStartInfo info = new ProcessStartInfo()
                {
                    FileName               = options.FileName,
                    UseShellExecute        = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true,
                    RedirectStandardInput  = true,
                    CreateNoWindow         = true,
                    WorkingDirectory       = options.CurrentDirectory._NullIfEmpty(),
                };

                if (options.ArgumentsList != null)
                {
                    options.ArgumentsList._DoForEach(a => info.ArgumentList.Add(a._NonNull()));
                }
                else
                {
                    info.Arguments = options.Arguments._NullIfZeroLen();
                }

                StartTick = Time.HighResTick64;

                Proc = Process.Start(info);

                this.ProcessId = Proc.Id;

                // 標準入出力を接続する
                this.StandardPipePoint_MySide = PipePoint.NewDuplexPipeAndGetOneSide(PipePointSide.A_LowerSide);
                this._InputOutputPipePoint    = this.StandardPipePoint_MySide.CounterPart._NullCheck();
                this.StandardPipeWrapper      = new PipePointStreamWrapper(StandardPipePoint_MySide, Proc.StandardOutput.BaseStream, Proc.StandardInput.BaseStream);

                // 標準エラー出力を接続する
                this.ErrorPipePoint_MySide = PipePoint.NewDuplexPipeAndGetOneSide(PipePointSide.A_LowerSide);
                this._ErrorPipePoint       = this.ErrorPipePoint_MySide.CounterPart._NullCheck();
                this.ErrorPipeWrapper      = new PipePointStreamWrapper(ErrorPipePoint_MySide, Proc.StandardError.BaseStream, Stream.Null);

                if (options.Flags.Bit(ExecFlags.EasyInputOutputMode))
                {
                    this.EasyInputOutputStub   = this._InputOutputPipePoint.GetNetAppProtocolStub(noCheckDisconnected: true);
                    this.EasyInputOutputStream = this.EasyInputOutputStub.GetStream();

                    this.EasyErrorStub   = this._ErrorPipePoint.GetNetAppProtocolStub(noCheckDisconnected: true);
                    this.EasyErrorStream = this.EasyErrorStub.GetStream();

                    if (options.EasyInputStr != null)
                    {
                        // 標準入力の注入タスク
                        this.EasyInputTask = this.EasyInputOutputStream.SendAsync(this.Options.EasyInputStr !._GetBytes(this.InputEncoding), this.GrandCancel)._LeakCheck();
                    }

                    // 標準出力の読み出しタスク
                    this.EasyOutputTask = this.EasyInputOutputStream._ReadWithMaxBufferSizeAsync(this.Options.EasyOutputMaxSize, this.GrandCancel)._LeakCheck();

                    // 標準エラー出力の読み出しタスク
                    this.EasyErrorTask = this.EasyErrorStream._ReadWithMaxBufferSizeAsync(this.Options.EasyOutputMaxSize, this.GrandCancel)._LeakCheck();
                }

                this.StartMainLoop(MainLoopAsync);
            }
            catch
            {
                this._DisposeSafe();
                throw;
            }
        }