private void RunCallback() { //While the process is running, we want the callback to run only periodically to provide the latest output. //Once the process exits, the output/error data handlers may keep firing as output/errors come back. There's no way to know when that's finished.. //To ensure that we capture the Command in its final state, we have to transmit the whole thing on every change after the process has exited. //The Callbacker helps with this somewhat by ensuring that the callback message being sent isn't identical to the previous one sent. if (HasExited) { Task.Run(() => Callbacker.Run()); } else { Task.Run(() => Callbacker.RunPeriodic()); } }
public Command(string guid, string path, string[] args, string callbackUrl = null, string callbackToken = null) { Guid = guid; Path = path; Args = args; CallbackToken = callbackToken; stdOutSb = new StringBuilder(); stdErrSb = new StringBuilder(); Callbacker = new Callbacker(this, callbackUrl); ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = path; if (args != null && args.Length > 0) { startInfo.Arguments = String.Join(" ", args); } startInfo.RedirectStandardError = true; startInfo.RedirectStandardOutput = true; startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; process = new Process(); process.EnableRaisingEvents = true; process.StartInfo = startInfo; process.ErrorDataReceived += new DataReceivedEventHandler(ErrorDataHandler); process.OutputDataReceived += new DataReceivedEventHandler(OutputDataHandler); process.Exited += new EventHandler(ExitedEventHandler); process.Start(); process.BeginErrorReadLine(); process.BeginOutputReadLine(); Log.Information("Created new command {Command}", Guid); Log.Verbose("New command properties: {@Command}", this); }
public void OnMayday() { //The service is shutting down. Make a last-ditch attempt to callback one more time and get in one final status... Mayday = true; Callbacker.Run(); }