public Task StopAsync(CancellationToken cancellationToken) { try { if (Proc != null && !Proc.HasExited) { Proc.Kill(); Proc.WaitForExit(10000); Proc.Close(); Proc.Dispose(); Proc = null; } } catch (Exception e) { Logger.Error("Stop", e); } return(Task.CompletedTask); }
private void StopNode() { try { if (Proc != null && !Proc.HasExited) { Proc.Kill(); if (!Proc.WaitForExit(10000)) /* wait 10 seconds */ { Logger.Warn("The process does not wait for completion."); } Proc.Close(); Proc.Dispose(); Proc = null; } } catch (Exception e) { Logger.Error("SocketIO failed stop", e); } }
private void StopRadicale() { try { if (Proc != null && !Proc.HasExited) { Proc.Kill(); if (!Proc.WaitForExit(10000)) { Logger.Warn("The process does not wait for completion."); } Proc.Close(); Proc.Dispose(); Proc = null; } } catch (Exception e) { Logger.Error("Radicale failed stop", e); } }
public virtual void Run() { //_success = false; //initial state to be defined by each inheriting class depending on it's handlers, we only update error conditions in this routine Process Proc = null; DateTime ExecutionStartTime; // Last thing to check, for custom commands, this will log an error and exit if (!File.Exists(_ApplicationPath)) { _jobStatus.ErrorMsg = "Application File Not Found"; _jobLog.WriteEntry(this, _jobStatus.ErrorMsg + " : " + _ApplicationPath, Log.LogEntryType.Error); _jobStatus.PercentageComplete = 0; _success = false; return; } if (_Parameters.Length > 8192) { _jobLog.WriteEntry(this, Localise.GetPhrase("Warning - command parameters exceeding 8192 characters. This may fail on some systems such as Windows XP"), Log.LogEntryType.Warning); } // Reset any progress counters _jobStatus.PercentageComplete = 0; _jobStatus.ETA = Localise.GetPhrase("Working") + "..."; //some processes like ReMuxSupp don't update perc, put a default message // Check if job has been cancelled, needed for some long running functions called Base if (_jobStatus.Cancelled) { _jobStatus.ErrorMsg = "Job cancelled, killing process"; _jobLog.WriteEntry(this, _jobStatus.ErrorMsg, Log.LogEntryType.Error); _success = false; //process has been terminated return; } try { if (_HangPeriod > 0) { _LastTick = DateTime.Now; } _jobLog.WriteEntry(this, "Launching process " + _ApplicationPath, Log.LogEntryType.Debug); _jobLog.WriteEntry(this, "Process arguments " + _Parameters, Log.LogEntryType.Debug); if (GlobalDefs.IsEngineRunningAsService) // these params only make sense when running as a service { _jobLog.WriteEntry(this, "UI Session Admin Process : " + _uiAdminSessionProcess.ToString(), Log.LogEntryType.Debug); } //Start the process ExecutionStartTime = DateTime.Now; // Check if we need to run a UISession process - It can only be run from a service, if we are running from a non service console, we don't need this // Apps like handbrake with hardware accelleration cannot run from a non UI session in windows (even in Windows 8 there are limitations with ffmpeg and OpenCL from Session 0) due to unavailability of hardware (OpenCL) API's in NonUI sessions mode // These apps needs to be started in a UI session separately to run // Check if we are running as a Service (Session 0 non UI Interactive) and if the user forcing use of UI Session 1 bool checkUICompliance = (GlobalDefs.IsEngineRunningAsService && _uiAdminSessionProcess); if (checkUICompliance) { _jobLog.WriteEntry(this, "Starting process as a UISession process with Admin privileges. This requires atleast 1 user to be logged into the system (remote desktop or locally)", Log.LogEntryType.Debug); uint procId = AppProcess.StartAppWithAdminPrivilegesFromNonUISession(_ApplicationPath, _Parameters, true, OutputHandler, _showWindow, _jobLog); if (procId == 0) { _jobLog.WriteEntry(this, "Unable to create UI Session process with Admin Privileges from NonUI Session. Is any user logged on?", Log.LogEntryType.Warning); _jobLog.WriteEntry(this, "Retrying process creation as a NonUI Session process with Admin privileges", Log.LogEntryType.Warning); _jobLog.WriteEntry(this, "Some functions like hardware encoding may not work in this mode", Log.LogEntryType.Warning); Proc = null; } else { Proc = Process.GetProcessById((int)procId); // Get the process identifier } } // Create the process if it hasn't already been created if (Proc == null) { //Set up the process Proc = new Process(); Proc.StartInfo.FileName = _ApplicationPath; Proc.StartInfo.Arguments = _Parameters; if (_showWindow) { Proc.StartInfo.CreateNoWindow = false; // for custom apps we create a window Proc.StartInfo.WindowStyle = ProcessWindowStyle.Normal; } else { Proc.StartInfo.CreateNoWindow = true; Proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; } Proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(_ApplicationPath); Proc.StartInfo.RedirectStandardOutput = true; Proc.StartInfo.RedirectStandardError = true; Proc.StartInfo.UseShellExecute = false; // always false else error handlers break Proc.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); Proc.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler); Proc.Start(); // First start the process else we get an exception Proc.BeginOutputReadLine(); Proc.BeginErrorReadLine(); } } catch (Exception Ex) { _jobStatus.ErrorMsg = "Unable to start process"; _jobLog.WriteEntry(this, _jobStatus.ErrorMsg + "\r\n" + Ex.Message, Log.LogEntryType.Error); _success = false; //process did not start return; // Exit now or we get an exception } // NOTE: Do all this after starting the process outside the catch block. Sometimes the process exists quickly (e.g. when process priority is IDLE) before this code runs and hence this code throws an exception try { _jobLog.WriteEntry(this, "Setting process priority to " + GlobalDefs.Priority.ToString(), Log.LogEntryType.Debug); Proc.PriorityClass = GlobalDefs.Priority; // Set the CPU Priority IOPriority.SetPriority(Proc.Handle, GlobalDefs.IOPriority); // Set the IO Priority if (MCEBuddyConf.GlobalMCEConfig.GeneralOptions.CPUAffinity != (IntPtr)0) { _jobLog.WriteEntry(this, "Setting CPU affinity to -> " + MCEBuddyConf.GlobalMCEConfig.GeneralOptions.CPUAffinity.ToString("d"), Log.LogEntryType.Debug); Proc.ProcessorAffinity = MCEBuddyConf.GlobalMCEConfig.GeneralOptions.CPUAffinity; } } catch (Exception e) { _jobLog.WriteEntry(this, "Error trying process priority or setting CPU affinity to -> " + MCEBuddyConf.GlobalMCEConfig.GeneralOptions.CPUAffinity.ToString("d") + "\n" + e.ToString(), Log.LogEntryType.Warning); } //Wait for an end while ((!Proc.HasExited)) { try { if (!_ignoreSuspend) // for some processes like ffmpegMediaInfo initiated by UI, we cannot block since it will hang the application { if (!isSuspended && GlobalDefs.Pause) // Check if process has to be suspended (if not already) { _jobLog.WriteEntry(this, "Suspending process", Log.LogEntryType.Information); IOPriority.SuspendProcess(Proc.Id); _jobLog.Flush(); // Flush the pending writes isSuspended = true; } if (isSuspended && !GlobalDefs.Pause) // Check if we need to resume the process { _jobLog.WriteEntry(this, "Resuming process", Log.LogEntryType.Information); isSuspended = false; _percentageHistory.Clear(); // Lose the history and start from here IOPriority.ResumeProcess(Proc.Id); } } if (Proc.PriorityClass != GlobalDefs.Priority) // Check if the priority was changed and if so update it { _jobLog.WriteEntry(this, "Process priority changed to " + GlobalDefs.Priority.ToString(), Log.LogEntryType.Information); Proc.PriorityClass = GlobalDefs.Priority; IOPriority.SetPriority(Proc.Handle, GlobalDefs.IOPriority); // First set the CPU priority } } catch { } //incase process exits in the background - not an issue, just avoid a crash if (_jobStatus.Cancelled) // if job has been cancelled kill the process { try { Proc.Kill(); _jobStatus.ErrorMsg = "Job cancelled, killing process"; _jobLog.WriteEntry(_jobStatus.ErrorMsg, Log.LogEntryType.Error); _success = false; //process has been terminated } catch (Exception Ex) { _jobStatus.ErrorMsg = "Job cancelled, unable to kill process"; _jobLog.WriteEntry(_jobStatus.ErrorMsg, Log.LogEntryType.Error); _jobLog.WriteEntry(Ex.Message, Log.LogEntryType.Warning); _success = false; //process has been terminated } break; } if (_unrecoverableError) { _jobLog.WriteEntry("Unrecoverable error encountered. Process likely hung, killing it", Log.LogEntryType.Error); _success = false; break; } if (isSuspended) { _LastTick = DateTime.Now; // Since during suspension there will be no output it shouldn't terminate the process } if ((_HangPeriod > 0) && (DateTime.Now > _LastTick.AddSeconds(_HangPeriod))) { _jobLog.WriteEntry("No response from process for " + _HangPeriod + " seconds, process likely hung - killing it", Log.LogEntryType.Error); _success = false; break; } System.Threading.Thread.Sleep(100); // sleep and check again } if (!_jobStatus.Cancelled) { System.Threading.Thread.Sleep(2000); //Allow the last set of messages to be written } if (!Proc.HasExited) // If we broke out of the loop, somethign bad happened { try { Proc.Kill(); _jobStatus.ErrorMsg = "Process hung, killing process"; _jobLog.WriteEntry(_jobStatus.ErrorMsg, Log.LogEntryType.Error); _success = false; //process has been terminated } catch (Exception Ex) { _jobStatus.ErrorMsg = "Unable to terminate process"; _jobLog.WriteEntry(_jobStatus.ErrorMsg + "\r\n" + Ex.Message, Log.LogEntryType.Error); _success = false; //process has been terminated } } else { // Sometimes for some reason the process exits without the output redirect async handlers completing causing failures // MSDN http://msdn.microsoft.com/en-us/library/fb4aw7b8(v=vs.110).aspx recommends using WaitForExit(x) followed by WaitForExit() to flush all output async handlers // TODO: Aysnc output is broken in .NET even with WaitForExit(), see http://alabaxblog.info/2013/06/redirectstandardoutput-beginoutputreadline-pattern-broken/ and http://stackoverflow.com/questions/9533070/how-to-read-to-end-process-output-asynchronously-in-c try { while (!Proc.WaitForExit(10)) { ; // Wait for it to return True } Proc.WaitForExit(); // Now wait for it to flush the buffers } catch { } _exitCode = Proc.ExitCode; // Store the exit code _jobLog.WriteEntry("Process exited with code " + _exitCode.ToString(), Log.LogEntryType.Debug); } _ExecutionTime = DateTime.Now - ExecutionStartTime; //Close out try { Proc.Close(); Proc.Dispose(); } catch (Exception Ex) { _jobLog.WriteEntry("Unable to cleanly close process" + "\r\n" + Ex.Message, Log.LogEntryType.Error); } Proc = null; if (!_jobStatus.Cancelled) { System.Threading.Thread.Sleep(100); //Allow for the process to be flush any pending messages } }