private void StartProcess(Process processToStart, string arguments, String executable, LogHandler logHandler, bool redirectStdin) { // Define handler of the completed process ProcessCompletionCallback processCompletionCallback = delegate(Process proc) { string msg = processToStart.Id + " - " + processToStart.StartInfo.FileName + " " + processToStart.StartInfo.Arguments; try { if (_orderlyShutdown) { LogEvent("Child process [" + msg + "] terminated with " + proc.ExitCode, EventLogEntryType.Information); } else { LogEvent("Child process [" + msg + "] finished with " + proc.ExitCode, EventLogEntryType.Warning); // if we finished orderly, report that to SCM. // by not reporting unclean shutdown, we let Windows SCM to decide if it wants to // restart the service automatically if (proc.ExitCode == 0) { SignalShutdownComplete(); } Environment.Exit(proc.ExitCode); } } catch (InvalidOperationException ioe) { LogEvent("WaitForExit " + ioe.Message); } try { proc.Dispose(); } catch (InvalidOperationException ioe) { LogEvent("Dispose " + ioe.Message); } }; // Invoke process and exit ProcessHelper.StartProcessAndCallbackForExit( processToStart: processToStart, executable: executable, arguments: arguments, envVars: _envs, workingDirectory: _descriptor.WorkingDirectory, priority: _descriptor.Priority, callback: processCompletionCallback, logHandler: logHandler, redirectStdin: redirectStdin); }
protected override void OnStart(string[] args) { _envs = _descriptor.EnvironmentVariables; // TODO: Disabled according to security concerns in https://github.com/kohsuke/winsw/issues/54 // Could be restored, but unlikely it's required in event logs at all /** * foreach (string key in _envs.Keys) * { * LogEvent("envar " + key + '=' + _envs[key]); * }*/ HandleFileCopies(); // handle downloads #if VNEXT List <Download> downloads = _descriptor.Downloads; Task[] tasks = new Task[downloads.Count]; for (int i = 0; i < downloads.Count; i++) { Download download = downloads[i]; string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}"; LogEvent(downloadMessage); Log.Info(downloadMessage); tasks[i] = download.PerformAsync(); } try { Task.WaitAll(tasks); } catch (AggregateException e) { List <Exception> exceptions = new List <Exception>(e.InnerExceptions.Count); for (int i = 0; i < tasks.Length; i++) { if (tasks[i].IsFaulted) { Download download = downloads[i]; string errorMessage = $"Failed to download {download.From} to {download.To}"; AggregateException exception = tasks[i].Exception !; LogEvent($"{errorMessage}. {exception.Message}"); Log.Error(errorMessage, exception); // TODO: move this code into the download logic if (download.FailOnError) { exceptions.Add(new IOException(errorMessage, exception)); } } } throw new AggregateException(exceptions); } #else foreach (Download download in _descriptor.Downloads) { string downloadMessage = $"Downloading: {download.From} to {download.To}. failOnError={download.FailOnError.ToString()}"; LogEvent(downloadMessage); Log.Info(downloadMessage); try { download.Perform(); } catch (Exception e) { string errorMessage = $"Failed to download {download.From} to {download.To}"; LogEvent($"{errorMessage}. {e.Message}"); Log.Error(errorMessage, e); // TODO: move this code into the download logic if (download.FailOnError) { throw new IOException(errorMessage, e); } // Else just keep going } } #endif string?startarguments = _descriptor.Startarguments; if (startarguments is null) { startarguments = _descriptor.Arguments; } else { startarguments += " " + _descriptor.Arguments; } LogEvent("Starting " + _descriptor.Executable + ' ' + startarguments); Log.Info("Starting " + _descriptor.Executable + ' ' + startarguments); // Load and start extensions ExtensionManager.LoadExtensions(); ExtensionManager.FireOnWrapperStarted(); LogHandler executableLogHandler = CreateExecutableLogHandler(); StartProcess(_process, startarguments, _descriptor.Executable, executableLogHandler, true); ExtensionManager.FireOnProcessStarted(_process); _process.StandardInput.Close(); // nothing for you to read! }
protected override void OnStart(string[] _) { _envs = _descriptor.EnvironmentVariables; // TODO: Disabled according to security concerns in https://github.com/kohsuke/winsw/issues/54 // Could be restored, but unlikely it's required in event logs at all /** * foreach (string key in _envs.Keys) * { * LogEvent("envar " + key + '=' + _envs[key]); * }*/ HandleFileCopies(); // handle downloads foreach (Download d in _descriptor.Downloads) { String downloadMsg = "Downloading: " + d.From + " to " + d.To + ". failOnError=" + d.FailOnError; LogEvent(downloadMsg); Log.Info(downloadMsg); try { d.Perform(); } catch (Exception e) { string errorMessage = "Failed to download " + d.From + " to " + d.To; LogEvent(errorMessage + ". " + e.Message); Log.Error(errorMessage, e); // TODO: move this code into the download logic if (d.FailOnError) { throw new IOException(errorMessage, e); } // Else just keep going } } string startarguments = _descriptor.Startarguments; if (startarguments == null) { startarguments = _descriptor.Arguments; } else { startarguments += " " + _descriptor.Arguments; } // Load and start extensions ExtensionManager.LoadExtensions(); ExtensionManager.FireOnWrapperStarted(); LogEvent("Starting " + _descriptor.Executable + ' ' + startarguments); Log.Info("Starting " + _descriptor.Executable + ' ' + startarguments); LogHandler executableLogHandler = CreateExecutableLogHandler(); StartProcess(_process, startarguments, _descriptor.Executable, executableLogHandler, true); ExtensionManager.FireOnProcessStarted(_process); _process.StandardInput.Close(); // nothing for you to read! }