//******************************************************************************************************// ProcessLauncher.cs - Gbtc//// Copyright © 2017, Grid Protection Alliance. All Rights Reserved.//// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See// the NOTICE file distributed with this work for additional information regarding copyright ownership.// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may// not use this file except in compliance with the License. You may obtain a copy of the License at://// http://opensource.org/licenses/MIT//// Unless agreed to in writing, the subject software distributed under the License is distributed on an// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the// License for the specific language governing permissions and limitations.//// Code Modification History:// ----------------------------------------------------------------------------------------------------// 11/29/2017 - J. Ritchie Carroll// Generated original version of source code.////****************************************************************************************************** using System;using System.Collections.Generic;using System.ComponentModel;using System.Diagnostics;using System.IO;using System.Linq;using System.Text;using System.Text.RegularExpressions;using GSF;using GSF.Diagnostics;using GSF.IO;using GSF.Threading;using GSF.TimeSeries;using GSF.TimeSeries.Adapters;using GSF.TimeSeries.Statistics;using GSF.Units; // Commands are passed via configuration#pragma warning disable SG0001 // ReSharper disable AssignNullToNotNullAttributenamespace FileAdapters{ /// <summary> /// Represents an adapter that will launch a configured executable process. /// </summary> /// <remarks> /// Unless credentials are provided to create an authentication context, rights of /// any launched executable will be limited to those available to time-series host. /// </remarks> [Description("Process Launcher: Launches a configured executable process on initialization")] public class ProcessLauncher : FacileActionAdapterBase { #region [ Members ] // Constants /// <summary> /// Default value for the <see cref="SupportsTemporalProcessing"/> property. /// </summary> public const bool DefaultSupportsTemporalProcessing = false; /// <summary> /// Default value for the <see cref="Arguments"/> property. /// </summary> public const string DefaultArguments = ""; /// <summary> /// Default value for the <see cref="WorkingDirectory"/> property. /// </summary> public const string DefaultWorkingDirectory = ""; /// <summary> /// Default value for the <see cref="EnvironmentalVariables"/> property. /// </summary> public const string DefaultEnvironmentalVariables = ""; /// <summary> /// Default value for the <see cref="CreateNoWindow"/> property. /// </summary> public const bool DefaultCreateNoWindow = true; /// <summary> /// Default value for the <see cref="WindowStyle"/> property. /// </summary> public const string DefaultWindowStyle = "Normal"; /// <summary> /// Default value for the <see cref="ErrorDialog"/> property. /// </summary> public const bool DefaultErrorDialog = false; /// <summary> /// Default value for the <see cref="Domain"/> property. /// </summary> public const string DefaultDomain = ""; /// <summary> /// Default value for the <see cref="UserName"/> property. /// </summary> public const string DefaultUserName = ""; /// <summary> /// Default value for the <see cref="Password"/> property. /// </summary> public const string DefaultPassword = ""; /// <summary> /// Default value for the <see cref="LoadUserProfile"/> property. /// </summary> public const bool DefaultLoadUserProfile = false; /// <summary> /// Default value for the <see cref="InitialInputFileName"/> property. /// </summary> public const string DefaultInitialInputFileName = ""; /// <summary> /// Default value for the <see cref="InitialInputProcessingDelay"/> property. /// </summary> public const int DefaultInitialInputProcessingDelay = 2000; /// <summary> /// Default value for the <see cref="RedirectOutputToHostEnvironment"/> property. /// </summary> public const bool DefaultRedirectOutputToHostEnvironment = true; /// <summary> /// Default value for the <see cref="RedirectErrorToHostEnvironment"/> property. /// </summary> public const bool DefaultRedirectErrorToHostEnvironment = true; /// <summary> /// Default value for the <see cref="ProcessOutputAsLogMessages"/> property. /// </summary> public const bool DefaultProcessOutputAsLogMessages = false; /// <summary> /// Default value for the <see cref="LogMessageTextExpression"/> property. /// </summary> public const string DefaultLogMessageTextExpression = @"(?<=.*msg\s*\=\s*\"")[^\""]*(?=\"")"; /// <summary> /// Default value for the <see cref="LogMessageLevelExpression"/> property. /// </summary> public const string DefaultLogMessageLevelExpression = @"(?<=.*lvl\s*\=\s*)[^\s]*(?=\s|$)"; /// <summary> /// Default value for the <see cref="LogMessageLevelMappings"/> property. /// </summary> public const string DefaultLogMessageLevelMappings = "info=Info; warn=Waning; error=Error; critical=Critical; debug=Debug"; /// <summary> /// Default value for the <see cref="ForceKillOnDispose"/> property. /// </summary> public const bool DefaultForceKillOnDispose = true; /// <summary> /// Default value for the <see cref="TrackProcessStatistics"/> property. /// </summary> public const bool DefaultTrackProcessStatistics = true; // Fields private readonly Process m_process; private readonly Dictionary<string, MessageLevel> m_messageLevelMap; private readonly ProcessUtilizationCalculator m_processUtilizationCalculator; private readonly ChildProcessManager m_childProcessManager; private Regex m_logMessageTextExpression; private Regex m_logMessageLevelExpression; private bool m_supportsTemporalProcessing; private long m_inputLinesProcessed; private long m_outputLinesProcessed; private long m_errorLinesProcessed; private bool m_disposed; #endregion #region [ Constructors ] /// <summary> /// Creates a new instance of the <see cref="ProcessLauncher"/> class. /// </summary> public ProcessLauncher() { m_process = new Process(); m_messageLevelMap = new Dictionary<string, MessageLevel>(StringComparer.OrdinalIgnoreCase); m_processUtilizationCalculator = new ProcessUtilizationCalculator(); // In Windows environments, make sure child processes can be terminated if parent is terminated - even if termination is not graceful if (!Common.IsPosixEnvironment) m_childProcessManager = new ChildProcessManager(); } #endregion #region [ Properties ] /// <summary> /// Gets the flag indicating if this adapter supports temporal processing. /// </summary> [ConnectionStringParameter, Description("Define the flag indicating if this adapter supports temporal processing."), DefaultValue(DefaultSupportsTemporalProcessing)] public override bool SupportsTemporalProcessing => m_supportsTemporalProcessing; /// <summary> /// Gets or sets the path and filename of executable to launch as a new process. /// </summary> [ConnectionStringParameter, Description("Define the path and filename of executable to launch as a new process.")] public string FileName { get; set; } /// <summary> /// Gets or sets any command line arguments to use when launching the process. /// </summary> [ConnectionStringParameter, Description("Define any command line arguments to use when launching the process."), DefaultValue(DefaultArguments)] public string Arguments { get; set; } = DefaultArguments; /// <summary> /// Gets or sets working directory to use when launching the process. /// </summary> [ConnectionStringParameter, Description("Define working directory to use when launching the process. Defaults to path of executable to launch."), DefaultValue(DefaultWorkingDirectory)] public string WorkingDirectory { get; set; } = DefaultWorkingDirectory; /// <summary> /// Gets or sets any needed environmental variables that should be set or updated before launching the process. /// </summary> [ConnectionStringParameter, Description("Define any needed environmental variables that should be set or updated before launching the process. Use connection string format to define variables, for example: variable1=value1; variable2=value2"), DefaultValue(DefaultEnvironmentalVariables)] public string EnvironmentalVariables { get; set; } = DefaultEnvironmentalVariables; /// <summary> /// Gets or sets flag that determines if a new window should be created when launching the process. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if a new window should be created when launching the process. This property is only applicable when adapter hosting environment can interact with a user interface."), DefaultValue(DefaultCreateNoWindow)] public bool CreateNoWindow { get; set; } = DefaultCreateNoWindow; /// <summary> /// Gets or sets window style to use when launching the process if creating a window. /// </summary> [ConnectionStringParameter, Description("Define window style to use when launching the process if creating a window. This property is only applicable when adapter hosting environment can interact with a user interface."), DefaultValue(typeof(ProcessWindowStyle), DefaultWindowStyle)] public ProcessWindowStyle WindowStyle { get; set; } = (ProcessWindowStyle)Enum.Parse(typeof(ProcessWindowStyle), DefaultWindowStyle); /// <summary> /// Gets or sets flag that determines if an error dialog should be displayed if the process cannot be launched. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if an error dialog should be displayed if the process cannot be launched. This property is only applicable when adapter hosting environment can interact with a user interface."), DefaultValue(DefaultErrorDialog)] public bool ErrorDialog { get; set; } = DefaultErrorDialog; /// <summary> /// Gets or sets the user domain to use when creating an authentication context before launching the process. /// </summary> [ConnectionStringParameter, Description("Define the user domain to use when creating an authentication context before launching the process. Leave blank to use authentication context of hosting environment."), DefaultValue(DefaultDomain)] public string Domain { get; set; } = DefaultDomain; /// <summary> /// Gets or sets the user name to use when creating an authentication context before launching the process. /// </summary> [ConnectionStringParameter, Description("Define the user name to use when creating an authentication context before launching the process. Leave blank to use authentication context of hosting environment."), DefaultValue(DefaultUserName)] public string UserName { get; set; } = DefaultUserName; /// <summary> /// Gets or sets the user password to use when creating an authentication context before launching the process. /// </summary> [ConnectionStringParameter, Description("Define the user password to use when creating an authentication context before launching the process. Leave blank to use authentication context of hosting environment."), DefaultValue(DefaultPassword)] public string Password { get; set; } = DefaultPassword; /// <summary> /// Gets or sets flag that determines if Windows user profile should be loaded from the registry before launching the process. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if Windows user profile should be loaded from the registry before launching the process."), DefaultValue(DefaultLoadUserProfile)] public bool LoadUserProfile { get; set; } = DefaultLoadUserProfile; /// <summary> /// Gets or sets filename that contains text to use as standard input into process after it has been launched. /// </summary> [ConnectionStringParameter, Description("Define filename that contains text to use as input into process after it has been launched. UTF-8 encoding assumed."), DefaultValue(DefaultInitialInputFileName)] public string InitialInputFileName { get; set; } = DefaultInitialInputFileName; /// <summary> /// Gets or sets the processing delay, in milliseconds, before text defined in the <see cref="InitialInputFileName"/> is sent to the launched process. /// </summary> [ConnectionStringParameter, Description("Define the processing delay, in milliseconds, before text defined in the InitialInputFileName is sent to the launched process."), DefaultValue(DefaultInitialInputProcessingDelay)] public int InitialInputProcessingDelay { get; set; } = DefaultInitialInputProcessingDelay; /// <summary> /// Gets or sets flag that determines if process standard output should be redirected to the hosting environment. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if process standard output should be redirected to the hosting environment."), DefaultValue(DefaultRedirectOutputToHostEnvironment)] public bool RedirectOutputToHostEnvironment { get; set; } = DefaultRedirectOutputToHostEnvironment; /// <summary> /// Gets or sets flag that determines if process standard error output should be redirected to the hosting environment. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if process standard error output should be redirected to the hosting environment."), DefaultValue(DefaultRedirectErrorToHostEnvironment)] public bool RedirectErrorToHostEnvironment { get; set; } = DefaultRedirectErrorToHostEnvironment; /// <summary> /// Gets or sets flag that determines if redirected output should be attempted to be parsed as formatted log messages, e.g.: lvl=info msg="log message". /// </summary> [ConnectionStringParameter, Description("Define flag that determines if redirected output should be attempted to be parsed as formatted log messages, e.g.: lvl=info msg=\"log message\"."), DefaultValue(DefaultProcessOutputAsLogMessages)] public bool ProcessOutputAsLogMessages { get; set; } = DefaultProcessOutputAsLogMessages; /// <summary> /// Gets or sets regular expression used to find log message text when redirected output is processed as formatted log messages. /// </summary> [ConnectionStringParameter, Description("Define regular expression used to find log message text when redirected output is processed as formatted log messages. Multiple matches will be joined as a single string."), DefaultValue(DefaultLogMessageTextExpression)] public string LogMessageTextExpression { get; set; } = DefaultLogMessageTextExpression; /// <summary> /// Gets or sets regular expression used to find log message level when redirected output is processed as formatted log messages. /// </summary> [ConnectionStringParameter, Description("Define regular expression used to find log message level when redirected output is processed as formatted log messages."), DefaultValue(DefaultLogMessageLevelExpression)] public string LogMessageLevelExpression { get; set; } = DefaultLogMessageLevelExpression; /// <summary> /// Gets or sets log level mappings to use when redirected output is processed as formatted log messages. /// </summary> [ConnectionStringParameter, Description("Define log level mappings to use when redirected output is processed as formatted log messages. Use connection string format as \"log_level_name=GSF.Diagnostics.MessageLevel\", for example: info=Info; warn=Waning; error=Error; critical=Critical; debug=Debug"), DefaultValue(DefaultLogMessageLevelMappings)] public string LogMessageLevelMappings { get; set; } = DefaultLogMessageLevelMappings; /// <summary> /// Gets or sets flag that determines if launched process should be forcibly terminated when adapter is disposed. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if launched process should be forcibly terminated when adapter is disposed."), DefaultValue(DefaultForceKillOnDispose)] public bool ForceKillOnDispose { get; set; } = DefaultForceKillOnDispose; /// <summary> /// Gets or sets the interval over which to calculate lunched process utilization. /// </summary> [ConnectionStringParameter, Description("Define the interval over which to update the lunched process CPU utilization. Set to 0 to disable utilization calculations."), DefaultValue(ProcessUtilizationCalculator.DefaultUpdateInterval)] public int UtilizationUpdateInterval { get; set; } = ProcessUtilizationCalculator.DefaultUpdateInterval; /// <summary> /// Gets or sets flag that determines if statistics should be tracked for launched process. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if statistics should be tracked for launched process."), DefaultValue(DefaultTrackProcessStatistics)] public bool TrackProcessStatistics { get; set; } = DefaultTrackProcessStatistics; #region [ Hidden Properties ] // The following common adapter properties are marked as never browse by an // editor since the properties are not used by the ProcessLauncher adapter /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new MeasurementKey[] InputMeasurementKeys { get { return base.InputMeasurementKeys; } set { base.InputMeasurementKeys = value; } } /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new IMeasurement[] OutputMeasurements { get { return base.OutputMeasurements; } set { base.OutputMeasurements = value; } } /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new int FramesPerSecond { get { return base.FramesPerSecond; } set { base.FramesPerSecond = value; } } /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new double LagTime { get { return base.LagTime; } set { base.LagTime = value; } } /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new double LeadTime { get { return base.LeadTime; } set { base.LeadTime = value; } } #endregion /// <summary> /// Returns the detailed status of the data input source. /// </summary> /// <remarks> /// Derived classes should extend status with implementation specific information. /// </remarks> public override string Status { get { StringBuilder status = new StringBuilder(); if (string.IsNullOrEmpty(WorkingDirectory)) WorkingDirectory = Directory.GetCurrentDirectory(); status.Append(base.Status); status.AppendLine($" Executable filename: {FilePath.TrimFileName(FileName, 51)}"); status.AppendLine($" Working directory: {FilePath.TrimFileName(WorkingDirectory, 51)}"); if (Initialized) { try { FileVersionInfo version = m_process.MainModule.FileVersionInfo; if (!string.IsNullOrWhiteSpace(version.FileVersion)) status.AppendLine($" Executable file version: {version.FileVersion}"); if (!string.IsNullOrWhiteSpace(version.FileDescription)) status.AppendLine($" Executable description: {version.FileDescription}");Lines 1–500 of 990. Load more
//****************************************************************************************************** // ProcessLauncher.cs - Gbtc // // Copyright © 2017, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 11/29/2017 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using GSF; using GSF.Diagnostics; using GSF.IO; using GSF.Threading; using GSF.TimeSeries; using GSF.TimeSeries.Adapters; using GSF.TimeSeries.Statistics; using GSF.Units; // Commands are passed via configuration #pragma warning disable SG0001 // ReSharper disable AssignNullToNotNullAttribute namespace FileAdapters { /// <summary> /// Represents an adapter that will launch a configured executable process. /// </summary> /// <remarks> /// Unless credentials are provided to create an authentication context, rights of /// any launched executable will be limited to those available to time-series host. /// </remarks> [Description("Process Launcher: Launches a configured executable process on initialization")] public class ProcessLauncher : FacileActionAdapterBase { #region [ Members ] // Constants /// <summary> /// Default value for the <see cref="SupportsTemporalProcessing"/> property. /// </summary> public const bool DefaultSupportsTemporalProcessing = false; /// <summary> /// Default value for the <see cref="Arguments"/> property. /// </summary> public const string DefaultArguments = ""; /// <summary> /// Default value for the <see cref="WorkingDirectory"/> property. /// </summary> public const string DefaultWorkingDirectory = ""; /// <summary> /// Default value for the <see cref="EnvironmentalVariables"/> property. /// </summary> public const string DefaultEnvironmentalVariables = ""; /// <summary> /// Default value for the <see cref="CreateNoWindow"/> property. /// </summary> public const bool DefaultCreateNoWindow = true; /// <summary> /// Default value for the <see cref="WindowStyle"/> property. /// </summary> public const string DefaultWindowStyle = "Normal"; /// <summary> /// Default value for the <see cref="ErrorDialog"/> property. /// </summary> public const bool DefaultErrorDialog = false; /// <summary> /// Default value for the <see cref="Domain"/> property. /// </summary> public const string DefaultDomain = ""; /// <summary> /// Default value for the <see cref="UserName"/> property. /// </summary> public const string DefaultUserName = ""; /// <summary> /// Default value for the <see cref="Password"/> property. /// </summary> public const string DefaultPassword = ""; /// <summary> /// Default value for the <see cref="LoadUserProfile"/> property. /// </summary> public const bool DefaultLoadUserProfile = false; /// <summary> /// Default value for the <see cref="InitialInputFileName"/> property. /// </summary> public const string DefaultInitialInputFileName = ""; /// <summary> /// Default value for the <see cref="InitialInputProcessingDelay"/> property. /// </summary> public const int DefaultInitialInputProcessingDelay = 2000; /// <summary> /// Default value for the <see cref="RedirectOutputToHostEnvironment"/> property. /// </summary> public const bool DefaultRedirectOutputToHostEnvironment = true; /// <summary> /// Default value for the <see cref="RedirectErrorToHostEnvironment"/> property. /// </summary> public const bool DefaultRedirectErrorToHostEnvironment = true; /// <summary> /// Default value for the <see cref="ProcessOutputAsLogMessages"/> property. /// </summary> public const bool DefaultProcessOutputAsLogMessages = false; /// <summary> /// Default value for the <see cref="LogMessageTextExpression"/> property. /// </summary> public const string DefaultLogMessageTextExpression = @"(?<=.*msg\s*\=\s*\"")[^\""]*(?=\"")"; /// <summary> /// Default value for the <see cref="LogMessageLevelExpression"/> property. /// </summary> public const string DefaultLogMessageLevelExpression = @"(?<=.*lvl\s*\=\s*)[^\s]*(?=\s|$)"; /// <summary> /// Default value for the <see cref="LogMessageLevelMappings"/> property. /// </summary> public const string DefaultLogMessageLevelMappings = "info=Info; warn=Waning; error=Error; critical=Critical; debug=Debug"; /// <summary> /// Default value for the <see cref="ForceKillOnDispose"/> property. /// </summary> public const bool DefaultForceKillOnDispose = true; /// <summary> /// Default value for the <see cref="TrackProcessStatistics"/> property. /// </summary> public const bool DefaultTrackProcessStatistics = true; // Fields private readonly Process m_process; private readonly Dictionary<string, MessageLevel> m_messageLevelMap; private readonly ProcessUtilizationCalculator m_processUtilizationCalculator; private readonly ChildProcessManager m_childProcessManager; private Regex m_logMessageTextExpression; private Regex m_logMessageLevelExpression; private bool m_supportsTemporalProcessing; private long m_inputLinesProcessed; private long m_outputLinesProcessed; private long m_errorLinesProcessed; private bool m_disposed; #endregion #region [ Constructors ] /// <summary> /// Creates a new instance of the <see cref="ProcessLauncher"/> class. /// </summary> public ProcessLauncher() { m_process = new Process(); m_messageLevelMap = new Dictionary<string, MessageLevel>(StringComparer.OrdinalIgnoreCase); m_processUtilizationCalculator = new ProcessUtilizationCalculator(); // In Windows environments, make sure child processes can be terminated if parent is terminated - even if termination is not graceful if (!Common.IsPosixEnvironment) m_childProcessManager = new ChildProcessManager(); } #endregion #region [ Properties ] /// <summary> /// Gets the flag indicating if this adapter supports temporal processing. /// </summary> [ConnectionStringParameter, Description("Define the flag indicating if this adapter supports temporal processing."), DefaultValue(DefaultSupportsTemporalProcessing)] public override bool SupportsTemporalProcessing => m_supportsTemporalProcessing; /// <summary> /// Gets or sets the path and filename of executable to launch as a new process. /// </summary> [ConnectionStringParameter, Description("Define the path and filename of executable to launch as a new process.")] public string FileName { get; set; } /// <summary> /// Gets or sets any command line arguments to use when launching the process. /// </summary> [ConnectionStringParameter, Description("Define any command line arguments to use when launching the process."), DefaultValue(DefaultArguments)] public string Arguments { get; set; } = DefaultArguments; /// <summary> /// Gets or sets working directory to use when launching the process. /// </summary> [ConnectionStringParameter, Description("Define working directory to use when launching the process. Defaults to path of executable to launch."), DefaultValue(DefaultWorkingDirectory)] public string WorkingDirectory { get; set; } = DefaultWorkingDirectory; /// <summary> /// Gets or sets any needed environmental variables that should be set or updated before launching the process. /// </summary> [ConnectionStringParameter, Description("Define any needed environmental variables that should be set or updated before launching the process. Use connection string format to define variables, for example: variable1=value1; variable2=value2"), DefaultValue(DefaultEnvironmentalVariables)] public string EnvironmentalVariables { get; set; } = DefaultEnvironmentalVariables; /// <summary> /// Gets or sets flag that determines if a new window should be created when launching the process. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if a new window should be created when launching the process. This property is only applicable when adapter hosting environment can interact with a user interface."), DefaultValue(DefaultCreateNoWindow)] public bool CreateNoWindow { get; set; } = DefaultCreateNoWindow; /// <summary> /// Gets or sets window style to use when launching the process if creating a window. /// </summary> [ConnectionStringParameter, Description("Define window style to use when launching the process if creating a window. This property is only applicable when adapter hosting environment can interact with a user interface."), DefaultValue(typeof(ProcessWindowStyle), DefaultWindowStyle)] public ProcessWindowStyle WindowStyle { get; set; } = (ProcessWindowStyle)Enum.Parse(typeof(ProcessWindowStyle), DefaultWindowStyle); /// <summary> /// Gets or sets flag that determines if an error dialog should be displayed if the process cannot be launched. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if an error dialog should be displayed if the process cannot be launched. This property is only applicable when adapter hosting environment can interact with a user interface."), DefaultValue(DefaultErrorDialog)] public bool ErrorDialog { get; set; } = DefaultErrorDialog; /// <summary> /// Gets or sets the user domain to use when creating an authentication context before launching the process. /// </summary> [ConnectionStringParameter, Description("Define the user domain to use when creating an authentication context before launching the process. Leave blank to use authentication context of hosting environment."), DefaultValue(DefaultDomain)] public string Domain { get; set; } = DefaultDomain; /// <summary> /// Gets or sets the user name to use when creating an authentication context before launching the process. /// </summary> [ConnectionStringParameter, Description("Define the user name to use when creating an authentication context before launching the process. Leave blank to use authentication context of hosting environment."), DefaultValue(DefaultUserName)] public string UserName { get; set; } = DefaultUserName; /// <summary> /// Gets or sets the user password to use when creating an authentication context before launching the process. /// </summary> [ConnectionStringParameter, Description("Define the user password to use when creating an authentication context before launching the process. Leave blank to use authentication context of hosting environment."), DefaultValue(DefaultPassword)] public string Password { get; set; } = DefaultPassword; /// <summary> /// Gets or sets flag that determines if Windows user profile should be loaded from the registry before launching the process. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if Windows user profile should be loaded from the registry before launching the process."), DefaultValue(DefaultLoadUserProfile)] public bool LoadUserProfile { get; set; } = DefaultLoadUserProfile; /// <summary> /// Gets or sets filename that contains text to use as standard input into process after it has been launched. /// </summary> [ConnectionStringParameter, Description("Define filename that contains text to use as input into process after it has been launched. UTF-8 encoding assumed."), DefaultValue(DefaultInitialInputFileName)] public string InitialInputFileName { get; set; } = DefaultInitialInputFileName; /// <summary> /// Gets or sets the processing delay, in milliseconds, before text defined in the <see cref="InitialInputFileName"/> is sent to the launched process. /// </summary> [ConnectionStringParameter, Description("Define the processing delay, in milliseconds, before text defined in the InitialInputFileName is sent to the launched process."), DefaultValue(DefaultInitialInputProcessingDelay)] public int InitialInputProcessingDelay { get; set; } = DefaultInitialInputProcessingDelay; /// <summary> /// Gets or sets flag that determines if process standard output should be redirected to the hosting environment. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if process standard output should be redirected to the hosting environment."), DefaultValue(DefaultRedirectOutputToHostEnvironment)] public bool RedirectOutputToHostEnvironment { get; set; } = DefaultRedirectOutputToHostEnvironment; /// <summary> /// Gets or sets flag that determines if process standard error output should be redirected to the hosting environment. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if process standard error output should be redirected to the hosting environment."), DefaultValue(DefaultRedirectErrorToHostEnvironment)] public bool RedirectErrorToHostEnvironment { get; set; } = DefaultRedirectErrorToHostEnvironment; /// <summary> /// Gets or sets flag that determines if redirected output should be attempted to be parsed as formatted log messages, e.g.: lvl=info msg="log message". /// </summary> [ConnectionStringParameter, Description("Define flag that determines if redirected output should be attempted to be parsed as formatted log messages, e.g.: lvl=info msg=\"log message\"."), DefaultValue(DefaultProcessOutputAsLogMessages)] public bool ProcessOutputAsLogMessages { get; set; } = DefaultProcessOutputAsLogMessages; /// <summary> /// Gets or sets regular expression used to find log message text when redirected output is processed as formatted log messages. /// </summary> [ConnectionStringParameter, Description("Define regular expression used to find log message text when redirected output is processed as formatted log messages. Multiple matches will be joined as a single string."), DefaultValue(DefaultLogMessageTextExpression)] public string LogMessageTextExpression { get; set; } = DefaultLogMessageTextExpression; /// <summary> /// Gets or sets regular expression used to find log message level when redirected output is processed as formatted log messages. /// </summary> [ConnectionStringParameter, Description("Define regular expression used to find log message level when redirected output is processed as formatted log messages."), DefaultValue(DefaultLogMessageLevelExpression)] public string LogMessageLevelExpression { get; set; } = DefaultLogMessageLevelExpression; /// <summary> /// Gets or sets log level mappings to use when redirected output is processed as formatted log messages. /// </summary> [ConnectionStringParameter, Description("Define log level mappings to use when redirected output is processed as formatted log messages. Use connection string format as \"log_level_name=GSF.Diagnostics.MessageLevel\", for example: info=Info; warn=Waning; error=Error; critical=Critical; debug=Debug"), DefaultValue(DefaultLogMessageLevelMappings)] public string LogMessageLevelMappings { get; set; } = DefaultLogMessageLevelMappings; /// <summary> /// Gets or sets flag that determines if launched process should be forcibly terminated when adapter is disposed. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if launched process should be forcibly terminated when adapter is disposed."), DefaultValue(DefaultForceKillOnDispose)] public bool ForceKillOnDispose { get; set; } = DefaultForceKillOnDispose; /// <summary> /// Gets or sets the interval over which to calculate lunched process utilization. /// </summary> [ConnectionStringParameter, Description("Define the interval over which to update the lunched process CPU utilization. Set to 0 to disable utilization calculations."), DefaultValue(ProcessUtilizationCalculator.DefaultUpdateInterval)] public int UtilizationUpdateInterval { get; set; } = ProcessUtilizationCalculator.DefaultUpdateInterval; /// <summary> /// Gets or sets flag that determines if statistics should be tracked for launched process. /// </summary> [ConnectionStringParameter, Description("Define flag that determines if statistics should be tracked for launched process."), DefaultValue(DefaultTrackProcessStatistics)] public bool TrackProcessStatistics { get; set; } = DefaultTrackProcessStatistics; #region [ Hidden Properties ] // The following common adapter properties are marked as never browse by an // editor since the properties are not used by the ProcessLauncher adapter /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new MeasurementKey[] InputMeasurementKeys { get { return base.InputMeasurementKeys; } set { base.InputMeasurementKeys = value; } } /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new IMeasurement[] OutputMeasurements { get { return base.OutputMeasurements; } set { base.OutputMeasurements = value; } } /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new int FramesPerSecond { get { return base.FramesPerSecond; } set { base.FramesPerSecond = value; } } /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new double LagTime { get { return base.LagTime; } set { base.LagTime = value; } } /// <summary> /// Property hidden - not used by <see cref="ProcessLauncher"/>. /// </summary> [EditorBrowsable(EditorBrowsableState.Never)] public new double LeadTime { get { return base.LeadTime; } set { base.LeadTime = value; } } #endregion /// <summary> /// Returns the detailed status of the data input source. /// </summary> /// <remarks> /// Derived classes should extend status with implementation specific information. /// </remarks> public override string Status { get { StringBuilder status = new StringBuilder(); if (string.IsNullOrEmpty(WorkingDirectory)) WorkingDirectory = Directory.GetCurrentDirectory(); status.Append(base.Status); status.AppendLine($" Executable filename: {FilePath.TrimFileName(FileName, 51)}"); status.AppendLine($" Working directory: {FilePath.TrimFileName(WorkingDirectory, 51)}"); if (Initialized) { try { FileVersionInfo version = m_process.MainModule.FileVersionInfo; if (!string.IsNullOrWhiteSpace(version.FileVersion)) status.AppendLine($" Executable file version: {version.FileVersion}"); if (!string.IsNullOrWhiteSpace(version.FileDescription)) status.AppendLine($" Executable description: {version.FileDescription}");