32 public string Name {
get;
internal set; }
33 public string Executable {
get;
internal set; }
35 private readonly List<string> _arguments =
new List<string>();
36 private Process _process;
37 private bool _hasWaitedOrExited;
45 Executable = executable;
58 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Cannot add arguments after starting.",
null, GPALObjectType.None);
63 GPAL.
PublishSimpleEvent(GPALEventType.ERROR,
"Argument cannot be null.",
null, GPALObjectType.None,
new ArgumentNullException(nameof(argument)));
66 _arguments.Add(argument);
78 bool shellExecute = Executable.StartsWith(
"http://", StringComparison.OrdinalIgnoreCase)
79 || Executable.StartsWith(
"https://", StringComparison.OrdinalIgnoreCase);
81 _process =
new Process
83 StartInfo =
new ProcessStartInfo
85 FileName = Executable,
86 Arguments =
string.Join(
" ", _arguments),
87 UseShellExecute = shellExecute,
88 RedirectStandardOutput =
false,
89 RedirectStandardError =
false,
90 CreateNoWindow = !shellExecute
101 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Failed to start [{Executable}]",
null, GPALObjectType.None, ex);
109 if (_process.StartInfo.RedirectStandardOutput)
115 _process.StartInfo.RedirectStandardOutput =
true;
116 _process.OutputDataReceived += (sender, e) => {
if (e.Data !=
null) outputHandler(e.Data); };
117 if (!_process.HasExited) _process.BeginOutputReadLine();
124 if (_process.StartInfo.RedirectStandardError)
130 _process.StartInfo.RedirectStandardError =
true;
131 _process.ErrorDataReceived += (sender, e) => {
if (e.Data !=
null) errorHandler(e.Data); };
132 if (!_process.HasExited) _process.BeginErrorReadLine();
139 if (directory ==
null)
141 GPAL.
PublishSimpleEvent(GPALEventType.WARNING,
"Working directory cannot be null.",
null, GPALObjectType.None,
new ArgumentNullException(nameof(directory)));
144 _process.StartInfo.WorkingDirectory = directory;
153 GPAL.
PublishSimpleEvent(GPALEventType.WARNING,
"Environment variable name cannot be null.",
null, GPALObjectType.None,
new ArgumentNullException(nameof(name)));
158 GPAL.
PublishSimpleEvent(GPALEventType.WARNING,
"Environment variable value cannot be null.",
null, GPALObjectType.None,
new ArgumentNullException(nameof(value)));
161 _process.StartInfo.EnvironmentVariables[name] = value;
174 _process.WaitForExit(milliseconds);
175 _hasWaitedOrExited =
true;
182 if (!_process.HasExited)
186 _hasWaitedOrExited =
true;
190 public void KillTree()
193 if (!_process.HasExited)
195 KillProcessTree(_process.Id);
198 _hasWaitedOrExited =
true;
201 private void KillProcessTree(
int pid)
206 using (var searcher =
new ManagementObjectSearcher(
207 $
"SELECT * FROM Win32_Process WHERE ParentProcessId = {pid}"))
209 foreach (ManagementObject obj
in searcher.Get())
211 int childPid = Convert.ToInt32(obj[
"ProcessId"]);
212 KillProcessTree(childPid);
215 Process.GetProcessById(childPid).Kill();
217 catch (ArgumentException)
226 GPAL.
PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Failed to kill process tree for PID [{pid}]",
null, GPALObjectType.None, ex);
229 public Launcher ToGPALObject()
234 private void EnsureStarted()
236 if (_process ==
null)
238 GPAL.
PublishSimpleEvent(GPALEventType.INFO,
"Process not started. Call Start() first.",
null, GPALObjectType.None);
243 private void EnsureRunning()
246 if (_process.HasExited || _hasWaitedOrExited)
247 GPAL.
PublishSimpleEvent(GPALEventType.INFO, $
"[{Executable}] is not running.",
null, GPALObjectType.None);
static void PublishSimpleEvent(GPALEventType gPALEventType, string msg, dynamic gPALObject=null, Enums.GPALObjectType gPALObjectType=GPALObjectType.None, Exception ex=null)
Publish a message to either the information channel or exception channel (if exception passed in) Pub...