You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
5.0 KiB

  1. #if NETFX
  2. using Apewer;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Text;
  7. namespace Apewer.Internals
  8. {
  9. /// <summary>控制台调用。</summary>
  10. internal sealed class ConsoleInvoker
  11. {
  12. private string _filename = "";
  13. private string _arguments = "";
  14. private bool _running = false;
  15. private Process _process = null;
  16. private Exception _exception = null;
  17. private StringBuilder _result = new StringBuilder();
  18. private List<string> _history = new List<string>();
  19. private Action _finished = null;
  20. private Action<string> _received = null;
  21. private ConsoleInvoker() { }
  22. /// <summary></summary>
  23. public bool Running { get { return _running; } }
  24. /// <summary></summary>
  25. public Action<string> Received { get { return _received; } }
  26. /// <summary></summary>
  27. public Action Finished { get { return _finished; } }
  28. /// <summary></summary>
  29. public Exception Exception { get { return _exception; } }
  30. /// <summary></summary>
  31. public Process Process { get { return _process; } }
  32. /// <summary></summary>
  33. public string FileName { get { return _filename ?? ""; } }
  34. /// <summary></summary>
  35. public string Arguments { get { return _arguments ?? ""; } }
  36. /// <summary></summary>
  37. public string Result { get { return _result.ToString(); } }
  38. /// <summary></summary>
  39. public void Abort()
  40. {
  41. PrivateStop();
  42. _running = false;
  43. }
  44. private void ProcessExited(object sender, EventArgs e)
  45. {
  46. PrivateStop();
  47. if (_finished != null) _finished();
  48. _running = false;
  49. }
  50. private void ProcessReceived(object sender, DataReceivedEventArgs e)
  51. {
  52. var data = e.Data ?? "";
  53. _result.Append(data);
  54. _result.Append("\r\n");
  55. _history.Add(data);
  56. if (_received != null) _received(data);
  57. }
  58. private void PrivateStop()
  59. {
  60. if (_process == null) return;
  61. _process.Close();
  62. _process.Dispose();
  63. _process = null;
  64. }
  65. private void PrivateRun(bool argSynchronizing)
  66. {
  67. _running = true;
  68. _process = new Process();
  69. _process.StartInfo.FileName = _filename;
  70. _process.StartInfo.Arguments = _arguments;
  71. _process.StartInfo.UseShellExecute = false; // 必须禁用操作系统外壳程序。
  72. _process.StartInfo.CreateNoWindow = true;
  73. _process.StartInfo.RedirectStandardOutput = true;
  74. if (argSynchronizing) PrivateSynchronizingRun();
  75. else PrivateAsynchronizingRun();
  76. }
  77. private void PrivateSynchronizingRun()
  78. {
  79. try
  80. {
  81. _process.Start();
  82. var output = _process.StandardOutput.ReadToEnd();
  83. if (output != null) _result.Append(output);
  84. _process.WaitForExit();
  85. _process.Close();
  86. }
  87. catch (Exception argException)
  88. {
  89. _exception = argException;
  90. }
  91. _process.Dispose();
  92. _process = null;
  93. _running = false;
  94. }
  95. private void PrivateAsynchronizingRun()
  96. {
  97. try
  98. {
  99. _process.EnableRaisingEvents = true;
  100. _process.Exited += ProcessExited;
  101. // 异步获取命令行内容。
  102. _process.Start();
  103. _process.BeginOutputReadLine();
  104. // 为异步获取订阅事件。
  105. _process.OutputDataReceived += new DataReceivedEventHandler(ProcessReceived);
  106. }
  107. catch (Exception argException)
  108. {
  109. _exception = argException;
  110. _running = false;
  111. }
  112. }
  113. /// <summary>运行进程并等待返回结果。</summary>
  114. public static ConsoleInvoker Run(string filename, string arguments)
  115. {
  116. var instance = new ConsoleInvoker();
  117. instance._filename = filename ?? "";
  118. instance._arguments = arguments ?? "";
  119. instance.PrivateRun(true);
  120. return instance;
  121. }
  122. /// <summary>运行进程,可指定事件回调。当回调均为 NULL 时将等待返回结果。</summary>
  123. public static ConsoleInvoker Run(string filename, string arguments, Action<string> received, Action finished)
  124. {
  125. var synchronizing = (received == null && finished == null) ? true : false;
  126. var instance = new ConsoleInvoker();
  127. instance._filename = filename ?? "";
  128. instance._arguments = arguments ?? "";
  129. instance._received = received;
  130. instance._finished = finished;
  131. instance.PrivateRun(synchronizing);
  132. return instance;
  133. }
  134. }
  135. }
  136. #endif