ClipboardProcessRunner.cs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #nullable enable
  2. using System.Diagnostics;
  3. namespace Terminal.Gui.App;
  4. /// <summary>
  5. /// Helper class for console drivers to invoke shell commands to interact with the clipboard. Used primarily by
  6. /// UnixDriver, but also used in Unit tests which is why it is in IDriver.cs.
  7. /// </summary>
  8. internal static class ClipboardProcessRunner
  9. {
  10. public static (int exitCode, string result) Bash (
  11. string commandLine,
  12. string inputText = "",
  13. bool waitForOutput = false
  14. )
  15. {
  16. var arguments = $"-c \"{commandLine}\"";
  17. (int exitCode, string result) = Process ("bash", arguments, inputText, waitForOutput);
  18. return (exitCode, result.TrimEnd ());
  19. }
  20. public static bool FileExists (this string value) { return !string.IsNullOrEmpty (value) && !value.Contains ("not found"); }
  21. public static (int exitCode, string result) Process (
  22. string cmd,
  23. string arguments,
  24. string? input = null,
  25. bool waitForOutput = true
  26. )
  27. {
  28. var output = string.Empty;
  29. using var process = new Process ();
  30. process.StartInfo = new()
  31. {
  32. FileName = cmd,
  33. Arguments = arguments,
  34. RedirectStandardOutput = true,
  35. RedirectStandardError = true,
  36. RedirectStandardInput = true,
  37. UseShellExecute = false,
  38. CreateNoWindow = true
  39. };
  40. TaskCompletionSource<bool> eventHandled = new ();
  41. process.Start ();
  42. if (!string.IsNullOrEmpty (input))
  43. {
  44. process.StandardInput.Write (input);
  45. process.StandardInput.Close ();
  46. }
  47. if (!process.WaitForExit (5000))
  48. {
  49. var timeoutError =
  50. $@"Process timed out. Command line: {process.StartInfo.FileName} {process.StartInfo.Arguments}.";
  51. throw new TimeoutException (timeoutError);
  52. }
  53. if (waitForOutput && process.StandardOutput.Peek () != -1)
  54. {
  55. output = process.StandardOutput.ReadToEnd ();
  56. }
  57. if (process.ExitCode > 0)
  58. {
  59. output = $@"Process failed to run. Command line: {cmd} {arguments}.
  60. Output: {output}
  61. Error: {process.StandardError.ReadToEnd ()}";
  62. }
  63. return (process.ExitCode, output);
  64. }
  65. }