public static ProcessResult RunProcess()

in Configurator/Base/Classes/Utilities.cs [1334:1439]


    public static ProcessResult RunProcess(string executableFilePath, string arguments, string workingDirectory, Action<string> outputRedirectionDelegate, Action<string> errorRedirectionDelegate, bool waitForExit, bool hideProcessMessages = false, bool waitLongerWorkaround = false)
    {
      if (string.IsNullOrEmpty(executableFilePath)
          || !File.Exists(executableFilePath))
      {
        return null;
      }

      ProcessResult result = null;
      try
      {
        if (string.IsNullOrEmpty(workingDirectory)
            || !Directory.Exists(workingDirectory))
        {
          workingDirectory = Path.GetDirectoryName(executableFilePath);
        }

        var processStartInfo = new ProcessStartInfo(executableFilePath)
        {
          Arguments = arguments.Trim(),
          RedirectStandardInput = true,
          RedirectStandardOutput = true,
          RedirectStandardError = true,
          UseShellExecute = false,
          CreateNoWindow = true
        };

        // It might seems this validation is not needed, but Path.GetDirectoryName name above could still return null or empty string.
        if (!string.IsNullOrEmpty(workingDirectory))
        {
          processStartInfo.WorkingDirectory = workingDirectory;
        }

        if (!hideProcessMessages)
        {
          outputRedirectionDelegate?.Invoke(string.Format(Resources.StartingProcessDetailsText, processStartInfo.FileName, processStartInfo.Arguments));
        }

        var process = Process.Start(processStartInfo);
        if (process == null)
        {
          return null;
        }

        int pid = process.Id;
        var outputBuilder = new StringBuilder();
        var errorBuilder = new StringBuilder();
        var processName = process.ProcessName;
        process.OutputDataReceived += (sender, e) =>
        {
          outputRedirectionDelegate?.Invoke(e.Data);
          outputBuilder.AppendLine(e.Data);
        };
        process.ErrorDataReceived += (sender, e) =>
        {
          errorRedirectionDelegate?.Invoke(e.Data);
          errorBuilder.AppendLine(e.Data);
        };
        process.BeginOutputReadLine();
        process.BeginErrorReadLine();
        process.StandardInput.Close();
        if (waitForExit)
        {
          if (waitLongerWorkaround)
          {
            while (!process.WaitForExit(3000))
            {
              if (GetRunningProcess(pid) != null)
              {
                // This is a dummy block, its intention is purely to act as a workaround for processes
                // that do not end gracefully when waiting for them indefinitely (like the MySQL Shell one).
              }
            }
          }
          else
          {
            // Wait indefinitely
            process.WaitForExit();
          }
        }

        result = new ProcessResult(
          process.HasExited ? null : process,
          process.HasExited ? (int?)process.ExitCode : null,
          outputBuilder.ToString(),
          errorBuilder.ToString());
        if (!hideProcessMessages)
        {
          outputRedirectionDelegate?.Invoke(!process.HasExited
          ? string.Format(Resources.StartedAndRunningProcessSuccessfullyText, processName, pid)
          : string.Format(Resources.StartedAndExitedProcessSuccessfullyText, processName, pid, process.ExitCode));
        }

        if (process.HasExited)
        {
          process.Dispose();
        }
      }
      catch (Exception ex)
      {
        Logger.LogException(ex);
        errorRedirectionDelegate?.Invoke(string.Format(Resources.StartedProcessErrorText, Path.GetFileNameWithoutExtension(executableFilePath), ex.Message));
      }

      return result;
    }