private Task RecordFromFile(MediaSourceInfo mediaSource, string inputFile, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { _targetPath = targetFile; _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile)); var process = _processFactory.Create(new ProcessOptions { CreateNoWindow = true, UseShellExecute = false, // Must consume both stdout and stderr or deadlocks may occur //RedirectStandardOutput = true, RedirectStandardError = true, RedirectStandardInput = true, FileName = _mediaEncoder.EncoderPath, Arguments = GetCommandLineArgs(mediaSource, inputFile, targetFile, duration), IsHidden = true, ErrorDialog = false, EnableRaisingEvents = true }); _process = process; var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments; _logger.LogInformation(commandLineLogMessage); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "record-transcode-" + Guid.NewGuid() + ".txt"); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. _logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(_json.SerializeToString(mediaSource) + Environment.NewLine + Environment.NewLine + commandLineLogMessage + Environment.NewLine + Environment.NewLine); _logFileStream.Write(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length); process.Exited += (sender, args) => OnFfMpegProcessExited(process, inputFile); process.Start(); cancellationToken.Register(Stop); // MUST read both stdout and stderr asynchronously or a deadlock may occurr //process.BeginOutputReadLine(); onStarted(); // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback StartStreamingLog(process.StandardError.BaseStream, _logFileStream); _logger.LogInformation("ffmpeg recording process started for {0}", _targetPath); return(_taskCompletionSource.Task); }
private bool ExecuteCommand(string cmdFilename, string cmdArguments) { bool processFailed = false; var process = ProcessFactory.Create( new ProcessOptions { CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, FileName = cmdFilename, Arguments = cmdArguments, IsHidden = true, ErrorDialog = false, EnableRaisingEvents = true } ); try { process.Start(); //StreamReader outputReader = process.StandardOutput.; //StreamReader errorReader = process.StandardError; Logger.Debug( "[{0}] Standard output from process is [{1}].", Name, process.StandardOutput.ReadToEnd() ); Logger.Debug( "[{0}] Standard error from process is [{1}].", Name, process.StandardError.ReadToEnd() ); } catch (Exception ex) { processFailed = true; Logger.Debug( "[{0}] Unhandled exception executing command, exception is [{1}].", Name, ex.Message ); } if (!processFailed && process.ExitCode == 0) { return(true); } else { return(false); } }
public void Setup() { IProcessFactory factory = Substitute.For <IProcessFactory>(); process = CreateTestProbe(); processId = Guid.NewGuid(); factory.Create(Arg.Any <IActorRefFactory>(), Arg.Any <SupervisorStrategy>()).Returns(process); manager = Sys.ActorOf(Props.Create(() => new Manager(factory))); }
private static IProcess Create(this IProcessFactory factory, ProcessArguments?args = null) { if (factory == null) { throw new ArgumentNullException(nameof(factory)); } return(factory.Create(args)); }
public void ProcessSimulationForStrategies(SingleProcessSimulation simulation, List <IStrategyFactory> strategyFactories) { foreach (var strategyFactory in strategyFactories) { simulation.PageList = _pageListPrototype.Clone(); simulation.FrameList = _frameListPrototype.Clone(); simulation.Process = _processFactory.Create(strategyFactory, _pageReferencesListPrototype.Clone()); simulation.ProcessAll(); } }
public void Execute(string program, string arguments) { var instructions = new ProcessInstructions { Program = program, Arguments = arguments }; if (_executor.ProcessInstance == null) { _executor.ProcessInstance = _processFactory.Create(instructions); } _executor.Execute(); }
public async Task Shutdown() { try { using var process = _processFactory.Create( new ProcessStartInfo(_dotNetCommandPathProvider.Path, $"build-server shutdown")); using var error = process.Output.Concat(process.Error) .Subscribe(x => _logger.Information(x)); await process.Run().ConfigureAwait(false); } catch (Exception e) { _logger.Error(e, "Error shutting down build server"); } }
private void Ready() { Receive <StartProcessCommand>(cmd => { logger.Info($"Creating process with Id: {cmd.Id}."); if (processes.ContainsKey(cmd.Id)) { logger.Error($"Process exists with Id: {cmd.Id}."); return; } var process = processFactory.Create(Context, Akka.Actor.SupervisorStrategy.StoppingStrategy); Context.Watch(process); processes.Add(cmd.Id, process); logger.Info($"Created process with Id: {cmd.Id}."); process.Forward(cmd); }); Receive <DomainEvent>(evnt => { if (!processes.ContainsKey(evnt.Id)) { logger.Error($"Could not delagate event to process with Id: {evnt.Id}."); return; } logger.Info($"Delegating event to process with Id: {evnt.Id}."); processes[evnt.Id].Tell(evnt); }); Receive <Terminated>(msg => { logger.Info("Removing process."); Guid key = (from actorRef in processes where Equals(actorRef.Value, msg.ActorRef) select actorRef.Key).DefaultIfEmpty(Guid.Empty).FirstOrDefault(); if (key == Guid.Empty) { logger.Warning("Could not remove process."); return; } logger.Info($"Removing process with Id: {key}."); processes.Remove(key); }); }
public BuildResult Execute(DotnetBuildInfo info) { if (!_toolResolver.TryResolve(Tool.Dotnet, out var dotnet)) { throw new InvalidOperationException($"Cannot find {Tool.Dotnet}."); } var process = _processFactory.Create( new ProcessInfo( dotnet, _workingDirectory, GetArgs().Concat(info.Arguments), Enumerable.Empty <EnvironmentVariable>())); process.Run(_processListener); return(_processListener.Result); }
public Task StartAsync(CancellationToken cancellationToken = default) { _logger.StartInvoked(GetType()); var process = _processFactory.Create(startInfo => { startInfo.FileName = _process; startInfo.Arguments = string.Join(' ', _args); }); _logger.ProcessCreated(process.Id); var result = process.Start(); _logger.ProcessStarted(process.Id, result); return(Task.FromResult(result ? 0 : 1)); }
public void Execute(TemplatePlanContext context) { var gitProcess = _processFactory .Create(p => { p.UseShellExecute = false; p.FileName = "git"; p.Arguments = "clone {0} {1}".ToFormat(context.Input.GitFlag, context.TempDir); }); gitProcess.Start(); gitProcess.WaitForExit(); if (gitProcess.ExitCode != 0) { throw new FubuException(gitProcess.ExitCode, "Command finished with a non-zero exit code"); } }
public IProcess Create(ProcessInfo info) { IProcessWrapper[] wrappers; lock (_wrappers) { wrappers = _wrappers.Reverse().ToArray(); } info = wrappers.Aggregate(info, (currentInfo, wrapper) => { LogInfo(currentInfo, "Before wrapping"); var result = wrapper.Wrap(currentInfo); LogInfo(result, "After wrapping"); return(result); }); return(_processFactory.Create(info)); }
private string GetProcessOutput(string path, string arguments) { IProcess process = _processFactory.Create(new ProcessOptions { CreateNoWindow = true, UseShellExecute = false, FileName = path, Arguments = arguments, IsHidden = true, ErrorDialog = false, RedirectStandardOutput = true, // ffmpeg uses stderr to log info, don't show this RedirectStandardError = true }); _logger.LogDebug("Running {Path} {Arguments}", path, arguments); using (process) { process.Start(); try { return(process.StandardOutput.ReadToEnd()); } catch { _logger.LogWarning("Killing process {Path} {Arguments}", path, arguments); // Hate having to do this try { process.Kill(); } catch (Exception ex) { _logger.LogError(ex, "Error killing process"); } throw; } } }
public bool TryFind(Path path, out Path fullPath) { var processInfo = new ProcessInfo(SearchTool, _workingDirectory, new[] { new CommandLineArgument(path.Value) }, Enumerable.Empty <EnvironmentVariable>()); var process = _processFactory.Create(processInfo); if (process.Run(this).Value != 0) { throw new InvalidOperationException($"Cannot run {SearchTool}."); } if (!string.IsNullOrWhiteSpace(_firstLine)) { fullPath = new Path(_firstLine); return(true); } fullPath = default(Path); return(false); }
private string GetProcessOutput(string path, string arguments) { var process = _processFactory.Create(new ProcessOptions { CreateNoWindow = true, UseShellExecute = false, FileName = path, Arguments = arguments, IsHidden = true, ErrorDialog = false, RedirectStandardOutput = true }); _logger.Info("Running {0} {1}", path, arguments); using (process) { process.Start(); try { return(process.StandardOutput.ReadToEnd()); } catch { _logger.Info("Killing process {0} {1}", path, arguments); // Hate having to do this try { process.Kill(); } catch (Exception ex1) { _logger.ErrorException("Error killing process", ex1); } throw; } } }
public void Run(TemplatePlanContext context, string rakeFile) { var tempFile = FileSystem.Combine(context.TempDir, "{0}.rb".ToFormat(Guid.NewGuid())); using (var runner = GetType().Assembly.GetManifestResourceStream(GetType(), "rakerunner.rb")) { using (var fileStream = File.Create(tempFile)) { runner.CopyTo(fileStream); using (var writer = new StreamWriter(fileStream)) { writer.WriteLine("FUBU_PROJECT_NAME = \"{0}\"".ToFormat(context.Input.ProjectName)); writer.WriteLine("Rake.application.run"); writer.Close(); } } } var rakeProcess = _processFactory .Create(s => { s.FileName = "ruby"; s.UseShellExecute = false; s.WorkingDirectory = context.TargetPath; s.Arguments = "{0} --rakefile {1}".ToFormat(tempFile, rakeFile); }); rakeProcess.Start(); rakeProcess.WaitForExit(); _fileSystem.DeleteFile(tempFile); if (rakeProcess.ExitCode != 0) { var message = new StringBuilder() .AppendLine("Command finished with a non-zero exit code") .AppendLine(rakeProcess.GetErrors()); throw new FubuException(rakeProcess.ExitCode, message.ToString()); } }
private void OnIntegrationFilesDropped(object sender, FileSystemEventArgs e) { if (string.IsNullOrWhiteSpace(e.FullPath)) { return; } try { // help prevent duplicate event calls _watcher.EnableRaisingEvents = false; IProcess process = _processFactory.Create(); process.Execute(e.FullPath); _watcher.EnableRaisingEvents = true; } catch (Exception ex) { _logger.LogError(ex, ex.Message); } }
/// <summary> /// Converts the text subtitle to SRT internal. /// </summary> /// <param name="inputPath">The input path.</param> /// <param name="inputProtocol">The input protocol.</param> /// <param name="outputPath">The output path.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException"> /// inputPath /// or /// outputPath /// </exception> private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) { throw new ArgumentNullException("inputPath"); } if (string.IsNullOrEmpty(outputPath)) { throw new ArgumentNullException("outputPath"); } _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath)); var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrEmpty(encodingParam)) { encodingParam = " -sub_charenc " + encodingParam; } var process = _processFactory.Create(new ProcessOptions { CreateNoWindow = true, UseShellExecute = false, FileName = _mediaEncoder.EncoderPath, Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), IsHidden = true, ErrorDialog = false }); _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); try { process.Start(); } catch (Exception ex) { _logger.ErrorException("Error starting ffmpeg", ex); throw; } var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); if (!ranToCompletion) { try { _logger.Info("Killing ffmpeg subtitle conversion process"); process.Kill(); } catch (Exception ex) { _logger.ErrorException("Error killing subtitle conversion process", ex); } } var exitCode = ranToCompletion ? process.ExitCode : -1; process.Dispose(); var failed = false; if (exitCode == -1) { failed = true; if (_fileSystem.FileExists(outputPath)) { try { _logger.Info("Deleting converted subtitle due to failure: ", outputPath); _fileSystem.DeleteFile(outputPath); } catch (IOException ex) { _logger.ErrorException("Error deleting converted subtitle {0}", ex, outputPath); } } } else if (!_fileSystem.FileExists(outputPath)) { failed = true; } if (failed) { var msg = string.Format("ffmpeg subtitle conversion failed for {0}", inputPath); _logger.Error(msg); throw new Exception(msg); } await SetAssFont(outputPath).ConfigureAwait(false); _logger.Info("ffmpeg subtitle conversion succeeded for {0}", inputPath); }
/// <summary> /// Converts the text subtitle to SRT internal. /// </summary> /// <param name="inputPath">The input path.</param> /// <param name="inputProtocol">The input protocol.</param> /// <param name="outputPath">The output path.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="ArgumentNullException"> /// inputPath /// or /// outputPath /// </exception> private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) { throw new ArgumentNullException(nameof(inputPath)); } if (string.IsNullOrEmpty(outputPath)) { throw new ArgumentNullException(nameof(outputPath)); } Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false); // FFmpeg automatically convert character encoding when it is UTF-16 // If we specify character encoding, it rejects with "do not specify a character encoding" and "Unable to recode subtitle event" if ((inputPath.EndsWith(".smi") || inputPath.EndsWith(".sami")) && (encodingParam == "UTF-16BE" || encodingParam == "UTF-16LE")) { encodingParam = ""; } else if (!string.IsNullOrEmpty(encodingParam)) { encodingParam = " -sub_charenc " + encodingParam; } var process = _processFactory.Create(new ProcessOptions { CreateNoWindow = true, UseShellExecute = false, FileName = _mediaEncoder.EncoderPath, Arguments = string.Format("{0} -i \"{1}\" -c:s srt \"{2}\"", encodingParam, inputPath, outputPath), EnableRaisingEvents = true, IsHidden = true, ErrorDialog = false }); _logger.LogInformation("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); try { process.Start(); } catch (Exception ex) { _logger.LogError(ex, "Error starting ffmpeg"); throw; } var ranToCompletion = await process.WaitForExitAsync(300000).ConfigureAwait(false); if (!ranToCompletion) { try { _logger.LogInformation("Killing ffmpeg subtitle conversion process"); process.Kill(); } catch (Exception ex) { _logger.LogError(ex, "Error killing subtitle conversion process"); } } var exitCode = ranToCompletion ? process.ExitCode : -1; process.Dispose(); var failed = false; if (exitCode == -1) { failed = true; if (File.Exists(outputPath)) { try { _logger.LogInformation("Deleting converted subtitle due to failure: ", outputPath); _fileSystem.DeleteFile(outputPath); } catch (IOException ex) { _logger.LogError(ex, "Error deleting converted subtitle {Path}", outputPath); } } } else if (!File.Exists(outputPath)) { failed = true; } if (failed) { _logger.LogError("ffmpeg subtitle conversion failed for {Path}", inputPath); throw new Exception( string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle conversion failed for {0}", inputPath)); } await SetAssFont(outputPath).ConfigureAwait(false); _logger.LogInformation("ffmpeg subtitle conversion succeeded for {Path}", inputPath); }
/// <summary> /// Runs specified process with specified arguments. /// </summary> /// <param name="fileName">The process to start.</param> /// <param name="arguments">The set of arguments to use when starting the process.</param> /// <returns>The process completion status.</returns> /// <exception cref="System.IO.FileNotFoundException">Occurs when the file to run is not found.</exception> /// <exception cref="InvalidOperationException">Occurs when this class instance is already running another process.</exception> public virtual CompletionStatus Run(string fileName, string arguments) { fileName.CheckNotNullOrEmpty(nameof(fileName)); IProcess p; lock (LockToken) { if (WorkProcess != null) { throw new InvalidOperationException(Resources.ProcessWorkerBusy); } p = _factory.Create(); WorkProcess = p; } _output.Clear(); _cancelWork = new CancellationTokenSource(); if (Options == null) { Options = new ProcessOptions(); } p.StartInfo.FileName = fileName; p.StartInfo.Arguments = arguments; CommandWithArgs = $@"""{fileName}"" {arguments}".TrimEnd(); if (OutputType == ProcessOutput.Output) { p.OutputDataReceived += OnDataReceived; } else if (OutputType == ProcessOutput.Error) { p.ErrorDataReceived += OnDataReceived; } if (Options.DisplayMode != ProcessDisplayMode.Native) { //if (Options.DisplayMode == ProcessDisplayMode.Interface && Config.UserInterfaceManager != null) //{ // Config.UserInterfaceManager.Display(Owner, this); //} p.StartInfo.CreateNoWindow = true; p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; if (OutputType == ProcessOutput.Output) { p.StartInfo.RedirectStandardOutput = true; } else if (OutputType == ProcessOutput.Error) { p.StartInfo.RedirectStandardError = true; } p.StartInfo.UseShellExecute = false; } ProcessStarted?.Invoke(this, new ProcessStartedEventArgs(this)); p.Start(); try { if (!p.HasExited) { p.PriorityClass = Options.Priority; } } catch (System.ComponentModel.Win32Exception) { } catch (InvalidOperationException) { } if (Options.DisplayMode != ProcessDisplayMode.Native) { if (OutputType == ProcessOutput.Output) { p.BeginOutputReadLine(); } else if (OutputType == ProcessOutput.Error) { p.BeginErrorReadLine(); } } var timeout = Wait(); // ExitCode is 0 for normal exit. Different value when closing the console. var result = timeout ? CompletionStatus.Timeout : _cancelWork.IsCancellationRequested ? CompletionStatus.Cancelled : p.ExitCode == 0 ? CompletionStatus.Success : CompletionStatus.Failed; _cancelWork = null; // Allow changing CompletionStatus in ProcessCompleted. var completedArgs = new ProcessCompletedEventArgs(result); ProcessCompleted?.Invoke(this, completedArgs); result = completedArgs.Status; LastCompletionStatus = result; //if ((result == CompletionStatus.Failed || result == CompletionStatus.Timeout) && Options.DisplayMode == ProcessDisplayMode.ErrorOnly) //{ // Config.UserInterfaceManager?.DisplayError(Owner, this); //} WorkProcess = null; return(result); }
public async Task <EncodingJob> Start(EncodingJobOptions options, IProgress <double> progress, CancellationToken cancellationToken) { var encodingJob = await new EncodingJobFactory(Logger, LibraryManager, MediaSourceManager, ConfigurationManager, MediaEncoder) .CreateJob(options, EncodingHelper, IsVideoEncoder, progress, cancellationToken).ConfigureAwait(false); encodingJob.OutputFilePath = GetOutputFilePath(encodingJob); FileSystem.CreateDirectory(FileSystem.GetDirectoryName(encodingJob.OutputFilePath)); encodingJob.ReadInputAtNativeFramerate = options.ReadInputAtNativeFramerate; await AcquireResources(encodingJob, cancellationToken).ConfigureAwait(false); var commandLineArgs = GetCommandLineArguments(encodingJob); var process = ProcessFactory.Create(new ProcessOptions { CreateNoWindow = true, UseShellExecute = false, // Must consume both stdout and stderr or deadlocks may occur //RedirectStandardOutput = true, RedirectStandardError = true, RedirectStandardInput = true, FileName = MediaEncoder.EncoderPath, Arguments = commandLineArgs, IsHidden = true, ErrorDialog = false, EnableRaisingEvents = true }); var workingDirectory = GetWorkingDirectory(options); if (!string.IsNullOrWhiteSpace(workingDirectory)) { process.StartInfo.WorkingDirectory = workingDirectory; } OnTranscodeBeginning(encodingJob); var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments; Logger.LogInformation(commandLineLogMessage); var logFilePath = Path.Combine(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt"); FileSystem.CreateDirectory(FileSystem.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. encodingJob.LogFileStream = FileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, true); var commandLineLogMessageBytes = Encoding.UTF8.GetBytes(commandLineLogMessage + Environment.NewLine + Environment.NewLine); await encodingJob.LogFileStream.WriteAsync(commandLineLogMessageBytes, 0, commandLineLogMessageBytes.Length, cancellationToken).ConfigureAwait(false); process.Exited += (sender, args) => OnFfMpegProcessExited(process, encodingJob); try { process.Start(); } catch (Exception ex) { Logger.LogError(ex, "Error starting ffmpeg"); OnTranscodeFailedToStart(encodingJob.OutputFilePath, encodingJob); throw; } cancellationToken.Register(() => Cancel(process, encodingJob)); // MUST read both stdout and stderr asynchronously or a deadlock may occurr //process.BeginOutputReadLine(); // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback new JobLogger(Logger).StartStreamingLog(encodingJob, process.StandardError.BaseStream, encodingJob.LogFileStream); // Wait for the file to exist before proceeeding while (!FileSystem.FileExists(encodingJob.OutputFilePath) && !encodingJob.HasExited) { await Task.Delay(100, cancellationToken).ConfigureAwait(false); } return(encodingJob); }
/// <summary> /// Runs specified application with specified arguments. /// </summary> /// <param name="fileName">The application to start.</param> /// <param name="arguments">The set of arguments to use when starting the application.</param> /// <returns>The process completion status.</returns> /// <exception cref="System.IO.FileNotFoundException">Occurs when the file to run is not found.</exception> /// <exception cref="InvalidOperationException">Occurs when this class instance is already running another process.</exception> public virtual CompletionStatus Run(string fileName, string arguments) { if (string.IsNullOrEmpty(fileName)) { throw new ArgumentException("Filename cannot be null or empty.", nameof(fileName)); } if (!fileSystem.Exists(fileName)) { throw new System.IO.FileNotFoundException(string.Format(@"File ""{0}"" is not found.", fileName)); } IProcess P; lock (lockToken) { if (WorkProcess != null) { throw new InvalidOperationException("This instance of FFmpegProcess is busy. You can run concurrent commands by creating other class instances."); } P = factory.Create(); WorkProcess = P; } output.Clear(); cancelWork = new CancellationTokenSource(); if (Options == null) { Options = new ProcessOptions(); } P.StartInfo.FileName = fileName; P.StartInfo.Arguments = arguments; CommandWithArgs = string.Format(@"""{0}"" {1}", fileName, arguments).TrimEnd(); if (OutputType == ProcessOutput.Output) { P.OutputDataReceived += OnDataReceived; } else if (OutputType == ProcessOutput.Error) { P.ErrorDataReceived += OnDataReceived; } if (Options.DisplayMode != FFmpegDisplayMode.Native) { if (Options.DisplayMode == FFmpegDisplayMode.Interface && Config.UserInterfaceManager != null) { Config.UserInterfaceManager.Display(this); } P.StartInfo.CreateNoWindow = true; P.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; if (OutputType == ProcessOutput.Output) { P.StartInfo.RedirectStandardOutput = true; } else if (OutputType == ProcessOutput.Error) { P.StartInfo.RedirectStandardError = true; } P.StartInfo.UseShellExecute = false; } ProcessStarted?.Invoke(this, new ProcessStartedEventArgs(this)); P.Start(); try { if (!P.HasExited) { P.PriorityClass = Options.Priority; } } catch { } if (Options.DisplayMode != FFmpegDisplayMode.Native) { if (OutputType == ProcessOutput.Output) { P.BeginOutputReadLine(); } else if (OutputType == ProcessOutput.Error) { P.BeginErrorReadLine(); } } bool Timeout = Wait(); // ExitCode is 0 for normal exit. Different value when closing the console. CompletionStatus Result = Timeout ? CompletionStatus.Timeout : cancelWork.IsCancellationRequested ? CompletionStatus.Cancelled : P.ExitCode == 0 ? CompletionStatus.Success : CompletionStatus.Failed; cancelWork = null; LastCompletionStatus = Result; ProcessCompleted?.Invoke(this, new ProcessCompletedEventArgs(Result)); if ((Result == CompletionStatus.Failed || Result == CompletionStatus.Timeout) && Options.DisplayMode == FFmpegDisplayMode.ErrorOnly) { Config.UserInterfaceManager?.DisplayError(this); } WorkProcess = null; return(Result); }