/// <summary> /// Invoked when the debug host is loading. By default this launches the remote service client. /// </summary> protected virtual void DebugHostLoading() { // Start remote console session string serviceClientName = ServiceClientName; if (!string.IsNullOrWhiteSpace(serviceClientName)) { m_processManager = new ChildProcessManager(); m_processManager.AddProcess(Process.Start(FilePath.GetAbsolutePath(serviceClientName))); } }
/// <summary> /// Initializes <see cref="ProcessLauncher"/>. /// </summary> public override void Initialize() { base.Initialize(); Dictionary <string, string> settings = Settings; ProcessWindowStyle windowStyle; int initialInputProcessingDelay, utilizationCalculationInterval; string setting; ProcessStartInfo startInfo = m_process.StartInfo; // Load required parameters if (settings.TryGetValue(nameof(FileName), out setting)) { setting = FilePath.GetAbsolutePath(setting.Trim()); if (File.Exists(setting)) { FileName = setting; startInfo.FileName = FileName; } else { throw new FileNotFoundException($"Cannot launch process: specified executable path and filename \"{setting}\" does not exist."); } } else { throw new ArgumentException($"Cannot launch process: required \"{nameof(FileName)}\" parameter is missing from connection string."); } // Load optional parameters if (settings.TryGetValue(nameof(SupportsTemporalProcessing), out setting)) { m_supportsTemporalProcessing = setting.ParseBoolean(); } else { m_supportsTemporalProcessing = DefaultSupportsTemporalProcessing; } if (settings.TryGetValue(nameof(Arguments), out setting) && setting.Length > 0) { startInfo.Arguments = setting; } if (settings.TryGetValue(nameof(WorkingDirectory), out setting)) { setting = setting.Trim(); if (Directory.Exists(setting)) { WorkingDirectory = setting; startInfo.WorkingDirectory = WorkingDirectory; } else { throw new DirectoryNotFoundException($"Cannot launch process: specified working directory \"{setting}\" does not exist."); } } else { WorkingDirectory = FilePath.GetDirectoryName(FileName); startInfo.WorkingDirectory = WorkingDirectory; } if (settings.TryGetValue(nameof(EnvironmentalVariables), out setting)) { foreach (KeyValuePair <string, string> item in setting.ParseKeyValuePairs()) { startInfo.Environment[item.Key] = item.Value; } } // Note that it's possible that time-series framework is being hosted by an application // running in a Window making many of the following process start properties relevant. // Even when hosted as a service, the user may start the service logging on using the // local system account and select to allow the service interact with the desktop. if (settings.TryGetValue(nameof(CreateNoWindow), out setting)) { startInfo.CreateNoWindow = setting.ParseBoolean(); } else { startInfo.CreateNoWindow = DefaultCreateNoWindow; } if (settings.TryGetValue(nameof(WindowStyle), out setting) && Enum.TryParse(setting, true, out windowStyle)) { startInfo.WindowStyle = windowStyle; } else { startInfo.WindowStyle = (ProcessWindowStyle)Enum.Parse(typeof(ProcessWindowStyle), DefaultWindowStyle); } if (settings.TryGetValue(nameof(ErrorDialog), out setting)) { startInfo.ErrorDialog = setting.ParseBoolean(); } else { startInfo.ErrorDialog = DefaultErrorDialog; } if (settings.TryGetValue(nameof(Domain), out setting) && setting.Length > 0) { startInfo.Domain = setting; } if (settings.TryGetValue(nameof(UserName), out setting) && setting.Length > 0) { startInfo.UserName = setting; } if (settings.TryGetValue(nameof(Password), out setting) && setting.Length > 0) { startInfo.Password = setting.ToSecureString(); } if (settings.TryGetValue(nameof(LoadUserProfile), out setting)) { startInfo.LoadUserProfile = setting.ParseBoolean(); } if (settings.TryGetValue(nameof(InitialInputFileName), out setting)) { setting = FilePath.GetAbsolutePath(setting.Trim()); if (File.Exists(setting)) { InitialInputFileName = setting; } else { throw new FileNotFoundException($"Cannot launch process: specified initial input filename \"{setting}\" does not exist."); } } if (settings.TryGetValue(nameof(InitialInputProcessingDelay), out setting) && int.TryParse(setting, out initialInputProcessingDelay) && initialInputProcessingDelay > -1) { InitialInputProcessingDelay = initialInputProcessingDelay; } if (settings.TryGetValue(nameof(RedirectOutputToHostEnvironment), out setting)) { RedirectOutputToHostEnvironment = setting.ParseBoolean(); } if (settings.TryGetValue(nameof(RedirectErrorToHostEnvironment), out setting)) { RedirectErrorToHostEnvironment = setting.ParseBoolean(); } if (settings.TryGetValue(nameof(UtilizationUpdateInterval), out setting) && int.TryParse(setting, out utilizationCalculationInterval)) { UtilizationUpdateInterval = utilizationCalculationInterval; } startInfo.RedirectStandardOutput = RedirectOutputToHostEnvironment; startInfo.RedirectStandardError = RedirectErrorToHostEnvironment; startInfo.RedirectStandardInput = true; startInfo.UseShellExecute = false; m_process.EnableRaisingEvents = true; m_process.OutputDataReceived += ProcessOutputDataReceived; m_process.ErrorDataReceived += ProcessErrorDataReceived; if (settings.TryGetValue(nameof(ProcessOutputAsLogMessages), out setting)) { ProcessOutputAsLogMessages = setting.ParseBoolean(); } if (ProcessOutputAsLogMessages) { if (settings.TryGetValue(nameof(LogMessageTextExpression), out setting) && setting.Length > 0) { LogMessageTextExpression = setting; } m_logMessageTextExpression = new Regex(LogMessageTextExpression, RegexOptions.Compiled); if (settings.TryGetValue(nameof(LogMessageLevelExpression), out setting) && setting.Length > 0) { LogMessageLevelExpression = setting; } m_logMessageLevelExpression = new Regex(LogMessageLevelExpression, RegexOptions.Compiled); if (settings.TryGetValue(nameof(LogMessageLevelMappings), out setting)) { LogMessageLevelMappings = setting; } foreach (KeyValuePair <string, string> item in LogMessageLevelMappings.ParseKeyValuePairs()) { MessageLevel level; if (Enum.TryParse(item.Value, true, out level)) { m_messageLevelMap[item.Key] = level; } } } if (settings.TryGetValue(nameof(ForceKillOnDispose), out setting)) { ForceKillOnDispose = setting.ParseBoolean(); } if (settings.TryGetValue(nameof(TrackProcessStatistics), out setting)) { TrackProcessStatistics = setting.ParseBoolean(); } m_process.Start(); if (ForceKillOnDispose) { m_childProcessManager?.AddProcess(m_process); } if (RedirectOutputToHostEnvironment) { m_process.BeginOutputReadLine(); } if (RedirectErrorToHostEnvironment) { m_process.BeginErrorReadLine(); } m_processUtilizationCalculator.UpdateInterval = UtilizationUpdateInterval; m_processUtilizationCalculator.Initialize(m_process); // Register launched process with the statistics engine if (TrackProcessStatistics) { StatisticsEngine.Register(this, "Process", "PROC"); } if (string.IsNullOrEmpty(InitialInputFileName)) { return; } // Send any defined initial input to launched application new Action(() => { try { using (StreamReader reader = File.OpenText(InitialInputFileName)) { string line; while ((object)(line = reader.ReadLine()) != null) { Input(line); } } } catch (Exception ex) { OnProcessException(MessageLevel.Warning, new InvalidOperationException($"Failed while sending text from \"{InitialInputFileName}\" to launched process standard input: {ex.Message}", ex)); } }) .DelayAndExecute(InitialInputProcessingDelay); }