//******************************************************************************************************
// ServiceHelper.cs - Gbtc
//
// Copyright © 2012, 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 Eclipse Public License -v 1.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/eclipse-1.0.php
//
// 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:
// ----------------------------------------------------------------------------------------------------
// 08/29/2006 - Pinal C. Patel
// Original version of source code generated.
// 11/30/2007 - Pinal C. Patel
// Modified the "design time" check in EndInit() method to use LicenseManager. UsageMode property
// instead of DesignMode property as the former is more accurate than the latter.
// 12/14/2007 - Pinal C. Patel
// Made monitoring of service health optional via the MonitorServiceHealth property.
// 09/30/2008 - J. Ritchie Carroll
// Converted to C#.
// 03/06/2009 - Pinal C. Patel
// Edited code comments.
// 06/19/2009 - Pinal C. Patel
// Modified Initialize() method to just load settings from the config file.
// 06/30/2009 - Pinal C. Patel
// Changed ServiceComponents to be a collection of object instead of ISupportLifecycle so it can
// host a wide range of object implementing various interfaces used by the ServiceHelper commands.
// 07/15/2009 - Pinal C. Patel
// Added AllowedRemoteUsers and ImpersonateRemoteUser properties as part of security.
// 07/16/2009 - Pinal C. Patel
// Added SupportTelnetSessions property so that telnet support can be optionally turned-on.
// 07/17/2009 - Pinal C. Patel
// Modified MonitorServiceHealth to default to false as it is not always needed.
// 07/30/2009 - Pinal C. Patel
// Modified to set the principal of the thread where client request are handled to that of the the
// process or remote client (if transmitted by the remote client upon connection).
// 08/07/2009 - Pinal C. Patel
// Subscribed to ErrorLogger.LoggingException event.
// 08/10/2009 - Josh L. Patterson
// Edited Comments
// 09/08/2009 - Pinal C. Patel
// Modified GetProcess(), GetConnectedClient() and GetClientRequestHandler() to use lambda
// functions instead of manual iteration of collection items.
// Renamed GetProcess(), GetConnectedClient() and GetClientRequestHandler() to FindProcess(),
// FindConnectedClient() and FindClientRequestHandler() respectively.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 10/23/2009 - Pinal C. Patel
// Modified UpdateStatus() method to allow the type of update to be specified.
// 12/18/2009 - Pinal C. Patel
// Added message flooding control to UpdateStatus().
// 06/16/2010 - Pinal C. Patel
// Made changes necessary to implement role-based security.
// Added thread synchronization to list-based member variable.
// 10/14/2010 - Pinal C. Patel
// Updated security implementation to include the entire client request text including command
// and arguments instead of just the command.
// 12/16/2010 - Pinal C. Patel
// Added SupportSystemCommands property that can be used to enable or disable system-level access
// via the build-in commands.
// 01/04/2011 - J. Ritchie Carroll
// Changed default performance sampling interval on services to every 5 seconds instead of every
// second to reduce overhead and increase performance. Added a "-lifetime" option to the Health
// command to show lifetime performance statistics. Made sampling interval a user config option.
// 01/17/2011 - J. Ritchie Carroll
// Added default "version" and "time" service commands.
// 02/11/2011 - Pinal C. Patel
// Updated VerifySecurity() to work correctly with TCP integrated windows authentication.
// 03/09/2011 - Pinal C. Patel
// Moved UpdateType enumeration to GSF namespace in GSF.Core.dll for broader usage.
// 04/14/2011 - Pinal C. Patel
// Updated to use new serialization methods in GSF.Serialization class.
// 09/22/2011 - J. Ritchie Carroll
// Added Mono implementation exception regions.
// 02/17/2012 - Stephen C. Wills
// Added ReloadCryptoCache service command.
// 04/12/2012 - Pinal C. Patel
// Added new UnscheduleProcess() and RemoveScheduledProcess methods.
// Changed AddProcess(), AddScheduledProcess() and ScheduleProcess() method to return a boolean.
// 12/20/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Security;
using System.Security.Principal;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using GSF.Collections;
using GSF.Communication;
using GSF.Configuration;
using GSF.Diagnostics;
using GSF.ErrorManagement;
using GSF.IO;
using GSF.Reflection;
using GSF.Scheduling;
using GSF.Security;
using GSF.Security.Cryptography;
namespace GSF.ServiceProcess
{
#region [ Enumerations ]
/// <summary>
/// Indicates the state of a Windows Service.
/// </summary>
public enum ServiceState
{
/// <summary>
/// Service has started.
/// </summary>
Started,
/// <summary>
/// Service has stopped.
/// </summary>
Stopped,
/// <summary>
/// Service has paused.
/// </summary>
Paused,
/// <summary>
/// Service has resumed.
/// </summary>
Resumed,
/// <summary>
/// Service has shutdown.
/// </summary>
Shutdown
}
#endregion
/// <summary>
/// Component that provides added functionality to a Windows Service.
/// </summary>
/// <seealso cref="ServiceProcess"/>
/// <seealso cref="ServiceResponse"/>
/// <seealso cref="ClientInfo"/>
/// <seealso cref="ClientRequest"/>
/// <seealso cref="ClientRequestHandler"/>
[ToolboxBitmap(typeof(ServiceHelper))]
public class ServiceHelper : Component, ISupportLifecycle, ISupportInitialize, IProvideStatus, IPersistSettings
{
#region [ Members ]
// Nested Types
private class StatusUpdate
{
public StatusUpdate(Guid client, UpdateType type, string message)
{
this.Client = client;
this.Type = type;
this.Message = message;
}
public readonly Guid Client;
public readonly UpdateType Type;
public readonly string Message;
}
// Constants
/// <summary>
/// Specifies the default value for the <see cref="LogStatusUpdates"/> property.
/// </summary>
public const bool DefaultLogStatusUpdates = true;
/// <summary>
/// Specifies the default value for the <see cref="MaxStatusUpdatesLength"/> property.
/// </summary>
public const int DefaultMaxStatusUpdatesLength = 8192;
/// <summary>
/// Specifies the default value for the <see cref="MaxStatusUpdatesFrequency"/> property.
/// </summary>
public const int DefaultMaxStatusUpdatesFrequency = 30;
/// <summary>
/// Specifies the default value for the <see cref="MonitorServiceHealth"/> property.
/// </summary>
public const bool DefaultMonitorServiceHealth = false;
/// <summary>
/// Specifies the default value for the <see cref="HealthMonitorInterval"/> property.
/// </summary>
public const double DefaultHealthMonitorInterval = 5.0D;
/// <summary>
/// Specifies the default value for the <see cref="RequestHistoryLimit"/> property.
/// </summary>
public const int DefaultRequestHistoryLimit = 50;
/// <summary>
/// Specifies the default value for the <see cref="SupportTelnetSessions"/> property.
/// </summary>
public const bool DefaultSupportTelnetSessions = false;
/// <summary>
/// Specifies the default value for the <see cref="SupportSystemCommands"/> property.
/// </summary>
public const bool DefaultSupportSystemCommands = false;
/// <summary>
/// Specifies the default value for the <see cref="SecureRemoteInteractions"/> property.
/// </summary>
public const bool DefaultSecureRemoteInteractions = false;
/// <summary>
/// Specifies the default value for the <see cref="PersistSettings"/> property.
/// </summary>
public const bool DefaultPersistSettings = false;
/// <summary>
/// Specifies the default value for the <see cref="SettingsCategory"/> property.
/// </summary>
public const string DefaultSettingsCategory = "ServiceHelper";
// Events
/// <summary>
/// Occurs when the <see cref="ParentService"/> is starting.
/// </summary>
[Category("Service"),
Description("Occurs when the ParentService is starting.")]
public event EventHandler<EventArgs<string[]>> ServiceStarting;
/// <summary>
/// Occurs when the <see cref="ParentService"/> has started.
/// </summary>
[Category("Service"),
Description("Occurs when the ParentService has started.")]
public event EventHandler ServiceStarted;
/// <summary>
/// Occurs when the <see cref="ParentService"/> is stopping.
/// </summary>
[Category("Service"),
Description("Occurs when the ParentService is stopping.")]
public event EventHandler ServiceStopping;
/// <summary>
/// Occurs when the <see cref="ParentService"/> has stopped.
/// </summary>
[Category("Service"),
Description("Occurs when the ParentService has stopped.")]
public event EventHandler ServiceStopped;
/// <summary>
/// Occurs when the <see cref="ParentService"/> is pausing.
/// </summary>
[Category("Service"),
Description("Occurs when the ParentService is pausing.")]
public event EventHandler ServicePausing;
/// <summary>
/// Occurs when the <see cref="ParentService"/> has paused.
/// </summary>
[Category("Service"),
Description("Occurs when the ParentService has paused.")]
public event EventHandler ServicePaused;
/// <summary>
/// Occurs when the <see cref="ParentService"/> is resuming.
/// </summary>
[Category("Service"),
Description("Occurs when the ParentService is resuming.")]
public event EventHandler ServiceResuming;
/// <summary>
/// Occurs when the <see cref="ParentService"/> has resumed.
/// </summary>
[Category("Service"),
Description("Occurs when the ParentService has resumed.")]
public event EventHandler ServiceResumed;
/// <summary>
/// Occurs when the system is being shutdown.
/// </summary>
[Category("System"),
Description("Occurs when the system is being shutdown.")]
public event EventHandler SystemShutdown;
/// <summary>
/// Occurs when a request is received from one of the <see cref="RemoteClients"/>.
/// </summary>
/// <remarks>
/// <see cref="EventArgs{T1,T2}.Argument1"/> is the ID of the remote client that sent the request.<br/>
/// <see cref="EventArgs{T1,T2}.Argument2"/> is the <see cref="ClientRequest"/> sent by the remote client.
/// </remarks>
[Category("Client"),
Description("Occurs when a request is received from one of the RemoteClients.")]
public event EventHandler<EventArgs<Guid, ClientRequest>> ReceivedClientRequest;
/// <summary>
/// Occurs when the state of a defiend <see cref="ServiceProcess"/> changes.
/// </summary>
/// <remarks>
/// <see cref="EventArgs{T1,T2}.Argument1"/> is the <see cref="ServiceProcess.Name"/>.<br/>
/// <see cref="EventArgs{T1,T2}.Argument2"/> is the <see cref="ServiceProcess.CurrentState"/>
/// </remarks>
[Category("Process"),
Description("Occurs when the state of a defiend ServiceProcess changes.")]
public event EventHandler<EventArgs<string, ServiceProcessState>> ProcessStateChanged;
// Fields
private bool m_logStatusUpdates;
private int m_maxStatusUpdatesLength;
private int m_maxStatusUpdatesFrequency;
private bool m_monitorServiceHealth;
private double m_healthMonitorInterval;
private int m_requestHistoryLimit;
private bool m_supportTelnetSessions;
private bool m_supportSystemCommands;
private bool m_secureRemoteInteractions;
private bool m_persistSettings;
private string m_settingsCategory;
private string m_telnetSessionPassword;
private ServiceBase m_parentService;
private ServerBase m_remotingServer;
private readonly LogFile m_statusLog;
private readonly ScheduleManager m_processScheduler;
private readonly ErrorLogger m_errorLogger;
private PerformanceMonitor m_performanceMonitor;
private readonly List<ServiceProcess> m_processes;
private readonly List<object> m_serviceComponents;
private readonly List<ClientInfo> m_remoteClients;
private readonly List<ClientRequestInfo> m_clientRequestHistory;
private readonly List<ClientRequestHandler> m_clientRequestHandlers;
private readonly Dictionary<ISupportLifecycle, bool> m_componentEnabledStates;
private readonly ProcessQueue<StatusUpdate> m_statusUpdateQueue;
private bool m_enabled;
private bool m_disposed;
private bool m_initialized;
private bool m_suppressUpdates;
private Guid m_remoteCommandClientID;
private Process m_remoteCommandProcess;
private Ticks m_lastStatusUpdateTime;
private int m_statusUpdatesDisplayed;
#endregion
#region [ Constructors ]
/// <summary>
/// Initializes a new instance of the <see cref="ServiceHelper"/> class.
/// </summary>
public ServiceHelper()
{
m_telnetSessionPassword = "s3cur3";
m_logStatusUpdates = DefaultLogStatusUpdates;
m_maxStatusUpdatesLength = DefaultMaxStatusUpdatesLength;
m_maxStatusUpdatesFrequency = DefaultMaxStatusUpdatesFrequency;
m_monitorServiceHealth = DefaultMonitorServiceHealth;
m_healthMonitorInterval = DefaultHealthMonitorInterval;
m_requestHistoryLimit = DefaultRequestHistoryLimit;
m_supportTelnetSessions = DefaultSupportTelnetSessions;
m_supportSystemCommands = DefaultSupportSystemCommands;
m_secureRemoteInteractions = DefaultSecureRemoteInteractions;
m_persistSettings = DefaultPersistSettings;
m_settingsCategory = DefaultSettingsCategory;
m_processes = new List<ServiceProcess>();
m_remoteClients = new List<ClientInfo>();
m_clientRequestHistory = new List<ClientRequestInfo>();
m_serviceComponents = new List<object>();
m_clientRequestHandlers = new List<ClientRequestHandler>();
m_componentEnabledStates = new Dictionary<ISupportLifecycle, bool>();
// Components
m_statusUpdateQueue = ProcessQueue<StatusUpdate>.CreateSynchronousQueue(ProcessStatusUpdates);
m_statusUpdateQueue.Name = "StatusUpdateQueue";
m_statusUpdateQueue.ProcessException += StatusUpdateQueue_ProcessException;
m_statusLog = new LogFile();
m_statusLog.FileName = "StatusLog.txt";
m_statusLog.SettingsCategory = "StatusLog";
m_statusLog.LogException += StatusLog_LogException;
m_processScheduler = new ScheduleManager();
m_processScheduler.SettingsCategory = "ProcessScheduler";
m_processScheduler.ScheduleDue += Scheduler_ScheduleDue;
m_errorLogger = new ErrorLogger();
m_errorLogger.ExitOnUnhandledException = false;
m_errorLogger.SettingsCategory = "ErrorLogger";
m_errorLogger.ErrorLog.SettingsCategory = "ErrorLog";
m_errorLogger.LoggingException += ErrorLogger_LoggingException;
}
/// <summary>
/// Initializes a new instance of the <see cref="ServiceHelper"/> class.
/// </summary>
/// <param name="container"><see cref="IContainer"/> object that contains the <see cref="ServiceHelper"/>.</param>
public ServiceHelper(IContainer container)
: this()
{
if (container != null)
container.Add(this);
}
#endregion
#region [ Properties ]
/// <summary>
/// Gets or sets a boolean value that indicates whether messages sent using <see cref="UpdateStatus(UpdateType,string,object[])"/>
/// or <see cref="UpdateStatus(Guid,UpdateType,string,object[])"/> are to be logged to the <see cref="StatusLog"/>.
/// </summary>
[Category("Updates"),
DefaultValue(DefaultLogStatusUpdates),
Description("Indicates whether messages sent using UpdateStatus() method overloads are to be logged to the StatusLog.")]
public bool LogStatusUpdates
{
get
{
return m_logStatusUpdates;
}
set
{
m_logStatusUpdates = value;
}
}
/// <summary>
/// Gets or sets the maximum numbers of characters allowed in update status messages without getting suppressed from being displayed.
/// </summary>
/// <exception cref="ArgumentException">The value being assigned is negative or zero.</exception>
[Category("Updates"),
DefaultValue(DefaultMaxStatusUpdatesLength),
Description("Maximum numbers of characters allowed in update status messages without getting suppressed from being displayed.")]
public int MaxStatusUpdatesLength
{
get
{
return m_maxStatusUpdatesLength;
}
set
{
if (value <= 0)
throw new ArgumentException("Value must be positive");
m_maxStatusUpdatesLength = value;
}
}
/// <summary>
/// Gets or sets the maximum number of status update messages that can be issued in a second without getting suppressed from being displayed.
/// </summary>
/// <exception cref="ArgumentException">The value being assigned is negative or zero.</exception>
[Category("Updates"),
DefaultValue(DefaultMaxStatusUpdatesFrequency),
Description("Maximum number of status update messages that can be issued in a second without getting suppressed from being displayed.")]
public int MaxStatusUpdatesFrequency
{
get
{
return m_maxStatusUpdatesFrequency;
}
set
{
if (value <= 0)
throw new ArgumentException("Value must be positive");
m_maxStatusUpdatesFrequency = value;
}
}
/// <summary>
/// Gets or sets a boolean value that indicates whether the health of the <see cref="ParentService"/> is to be monitored.
/// </summary>
[Category("Settings"),
DefaultValue(DefaultMonitorServiceHealth),
Description("Indicates whether the health of the ParentService is to be monitored.")]
public bool MonitorServiceHealth
{
get
{
return m_monitorServiceHealth;
}
set
{
m_monitorServiceHealth = value;
}
}
/// <summary>
Lines 1–500 of 3711. Load more
//****************************************************************************************************** // ServiceHelper.cs - Gbtc // // Copyright © 2012, 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 Eclipse Public License -v 1.0 (the "License"); you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/eclipse-1.0.php // // 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: // ---------------------------------------------------------------------------------------------------- // 08/29/2006 - Pinal C. Patel // Original version of source code generated. // 11/30/2007 - Pinal C. Patel // Modified the "design time" check in EndInit() method to use LicenseManager. UsageMode property // instead of DesignMode property as the former is more accurate than the latter. // 12/14/2007 - Pinal C. Patel // Made monitoring of service health optional via the MonitorServiceHealth property. // 09/30/2008 - J. Ritchie Carroll // Converted to C#. // 03/06/2009 - Pinal C. Patel // Edited code comments. // 06/19/2009 - Pinal C. Patel // Modified Initialize() method to just load settings from the config file. // 06/30/2009 - Pinal C. Patel // Changed ServiceComponents to be a collection of object instead of ISupportLifecycle so it can // host a wide range of object implementing various interfaces used by the ServiceHelper commands. // 07/15/2009 - Pinal C. Patel // Added AllowedRemoteUsers and ImpersonateRemoteUser properties as part of security. // 07/16/2009 - Pinal C. Patel // Added SupportTelnetSessions property so that telnet support can be optionally turned-on. // 07/17/2009 - Pinal C. Patel // Modified MonitorServiceHealth to default to false as it is not always needed. // 07/30/2009 - Pinal C. Patel // Modified to set the principal of the thread where client request are handled to that of the the // process or remote client (if transmitted by the remote client upon connection). // 08/07/2009 - Pinal C. Patel // Subscribed to ErrorLogger.LoggingException event. // 08/10/2009 - Josh L. Patterson // Edited Comments // 09/08/2009 - Pinal C. Patel // Modified GetProcess(), GetConnectedClient() and GetClientRequestHandler() to use lambda // functions instead of manual iteration of collection items. // Renamed GetProcess(), GetConnectedClient() and GetClientRequestHandler() to FindProcess(), // FindConnectedClient() and FindClientRequestHandler() respectively. // 09/14/2009 - Stephen C. Wills // Added new header and license agreement. // 10/23/2009 - Pinal C. Patel // Modified UpdateStatus() method to allow the type of update to be specified. // 12/18/2009 - Pinal C. Patel // Added message flooding control to UpdateStatus(). // 06/16/2010 - Pinal C. Patel // Made changes necessary to implement role-based security. // Added thread synchronization to list-based member variable. // 10/14/2010 - Pinal C. Patel // Updated security implementation to include the entire client request text including command // and arguments instead of just the command. // 12/16/2010 - Pinal C. Patel // Added SupportSystemCommands property that can be used to enable or disable system-level access // via the build-in commands. // 01/04/2011 - J. Ritchie Carroll // Changed default performance sampling interval on services to every 5 seconds instead of every // second to reduce overhead and increase performance. Added a "-lifetime" option to the Health // command to show lifetime performance statistics. Made sampling interval a user config option. // 01/17/2011 - J. Ritchie Carroll // Added default "version" and "time" service commands. // 02/11/2011 - Pinal C. Patel // Updated VerifySecurity() to work correctly with TCP integrated windows authentication. // 03/09/2011 - Pinal C. Patel // Moved UpdateType enumeration to GSF namespace in GSF.Core.dll for broader usage. // 04/14/2011 - Pinal C. Patel // Updated to use new serialization methods in GSF.Serialization class. // 09/22/2011 - J. Ritchie Carroll // Added Mono implementation exception regions. // 02/17/2012 - Stephen C. Wills // Added ReloadCryptoCache service command. // 04/12/2012 - Pinal C. Patel // Added new UnscheduleProcess() and RemoveScheduledProcess methods. // Changed AddProcess(), AddScheduledProcess() and ScheduleProcess() method to return a boolean. // 12/20/2012 - Starlynn Danyelle Gilliam // Modified Header. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.ComponentModel; using System.Configuration; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Security; using System.Security.Principal; using System.ServiceProcess; using System.Text; using System.Threading; using GSF.Collections; using GSF.Communication; using GSF.Configuration; using GSF.Diagnostics; using GSF.ErrorManagement; using GSF.IO; using GSF.Reflection; using GSF.Scheduling; using GSF.Security; using GSF.Security.Cryptography; namespace GSF.ServiceProcess { #region [ Enumerations ] /// <summary> /// Indicates the state of a Windows Service. /// </summary> public enum ServiceState { /// <summary> /// Service has started. /// </summary> Started, /// <summary> /// Service has stopped. /// </summary> Stopped, /// <summary> /// Service has paused. /// </summary> Paused, /// <summary> /// Service has resumed. /// </summary> Resumed, /// <summary> /// Service has shutdown. /// </summary> Shutdown } #endregion /// <summary> /// Component that provides added functionality to a Windows Service. /// </summary> /// <seealso cref="ServiceProcess"/> /// <seealso cref="ServiceResponse"/> /// <seealso cref="ClientInfo"/> /// <seealso cref="ClientRequest"/> /// <seealso cref="ClientRequestHandler"/> [ToolboxBitmap(typeof(ServiceHelper))] public class ServiceHelper : Component, ISupportLifecycle, ISupportInitialize, IProvideStatus, IPersistSettings { #region [ Members ] // Nested Types private class StatusUpdate { public StatusUpdate(Guid client, UpdateType type, string message) { this.Client = client; this.Type = type; this.Message = message; } public readonly Guid Client; public readonly UpdateType Type; public readonly string Message; } // Constants /// <summary> /// Specifies the default value for the <see cref="LogStatusUpdates"/> property. /// </summary> public const bool DefaultLogStatusUpdates = true; /// <summary> /// Specifies the default value for the <see cref="MaxStatusUpdatesLength"/> property. /// </summary> public const int DefaultMaxStatusUpdatesLength = 8192; /// <summary> /// Specifies the default value for the <see cref="MaxStatusUpdatesFrequency"/> property. /// </summary> public const int DefaultMaxStatusUpdatesFrequency = 30; /// <summary> /// Specifies the default value for the <see cref="MonitorServiceHealth"/> property. /// </summary> public const bool DefaultMonitorServiceHealth = false; /// <summary> /// Specifies the default value for the <see cref="HealthMonitorInterval"/> property. /// </summary> public const double DefaultHealthMonitorInterval = 5.0D; /// <summary> /// Specifies the default value for the <see cref="RequestHistoryLimit"/> property. /// </summary> public const int DefaultRequestHistoryLimit = 50; /// <summary> /// Specifies the default value for the <see cref="SupportTelnetSessions"/> property. /// </summary> public const bool DefaultSupportTelnetSessions = false; /// <summary> /// Specifies the default value for the <see cref="SupportSystemCommands"/> property. /// </summary> public const bool DefaultSupportSystemCommands = false; /// <summary> /// Specifies the default value for the <see cref="SecureRemoteInteractions"/> property. /// </summary> public const bool DefaultSecureRemoteInteractions = false; /// <summary> /// Specifies the default value for the <see cref="PersistSettings"/> property. /// </summary> public const bool DefaultPersistSettings = false; /// <summary> /// Specifies the default value for the <see cref="SettingsCategory"/> property. /// </summary> public const string DefaultSettingsCategory = "ServiceHelper"; // Events /// <summary> /// Occurs when the <see cref="ParentService"/> is starting. /// </summary> [Category("Service"), Description("Occurs when the ParentService is starting.")] public event EventHandler<EventArgs<string[]>> ServiceStarting; /// <summary> /// Occurs when the <see cref="ParentService"/> has started. /// </summary> [Category("Service"), Description("Occurs when the ParentService has started.")] public event EventHandler ServiceStarted; /// <summary> /// Occurs when the <see cref="ParentService"/> is stopping. /// </summary> [Category("Service"), Description("Occurs when the ParentService is stopping.")] public event EventHandler ServiceStopping; /// <summary> /// Occurs when the <see cref="ParentService"/> has stopped. /// </summary> [Category("Service"), Description("Occurs when the ParentService has stopped.")] public event EventHandler ServiceStopped; /// <summary> /// Occurs when the <see cref="ParentService"/> is pausing. /// </summary> [Category("Service"), Description("Occurs when the ParentService is pausing.")] public event EventHandler ServicePausing; /// <summary> /// Occurs when the <see cref="ParentService"/> has paused. /// </summary> [Category("Service"), Description("Occurs when the ParentService has paused.")] public event EventHandler ServicePaused; /// <summary> /// Occurs when the <see cref="ParentService"/> is resuming. /// </summary> [Category("Service"), Description("Occurs when the ParentService is resuming.")] public event EventHandler ServiceResuming; /// <summary> /// Occurs when the <see cref="ParentService"/> has resumed. /// </summary> [Category("Service"), Description("Occurs when the ParentService has resumed.")] public event EventHandler ServiceResumed; /// <summary> /// Occurs when the system is being shutdown. /// </summary> [Category("System"), Description("Occurs when the system is being shutdown.")] public event EventHandler SystemShutdown; /// <summary> /// Occurs when a request is received from one of the <see cref="RemoteClients"/>. /// </summary> /// <remarks> /// <see cref="EventArgs{T1,T2}.Argument1"/> is the ID of the remote client that sent the request.<br/> /// <see cref="EventArgs{T1,T2}.Argument2"/> is the <see cref="ClientRequest"/> sent by the remote client. /// </remarks> [Category("Client"), Description("Occurs when a request is received from one of the RemoteClients.")] public event EventHandler<EventArgs<Guid, ClientRequest>> ReceivedClientRequest; /// <summary> /// Occurs when the state of a defiend <see cref="ServiceProcess"/> changes. /// </summary> /// <remarks> /// <see cref="EventArgs{T1,T2}.Argument1"/> is the <see cref="ServiceProcess.Name"/>.<br/> /// <see cref="EventArgs{T1,T2}.Argument2"/> is the <see cref="ServiceProcess.CurrentState"/> /// </remarks> [Category("Process"), Description("Occurs when the state of a defiend ServiceProcess changes.")] public event EventHandler<EventArgs<string, ServiceProcessState>> ProcessStateChanged; // Fields private bool m_logStatusUpdates; private int m_maxStatusUpdatesLength; private int m_maxStatusUpdatesFrequency; private bool m_monitorServiceHealth; private double m_healthMonitorInterval; private int m_requestHistoryLimit; private bool m_supportTelnetSessions; private bool m_supportSystemCommands; private bool m_secureRemoteInteractions; private bool m_persistSettings; private string m_settingsCategory; private string m_telnetSessionPassword; private ServiceBase m_parentService; private ServerBase m_remotingServer; private readonly LogFile m_statusLog; private readonly ScheduleManager m_processScheduler; private readonly ErrorLogger m_errorLogger; private PerformanceMonitor m_performanceMonitor; private readonly List<ServiceProcess> m_processes; private readonly List<object> m_serviceComponents; private readonly List<ClientInfo> m_remoteClients; private readonly List<ClientRequestInfo> m_clientRequestHistory; private readonly List<ClientRequestHandler> m_clientRequestHandlers; private readonly Dictionary<ISupportLifecycle, bool> m_componentEnabledStates; private readonly ProcessQueue<StatusUpdate> m_statusUpdateQueue; private bool m_enabled; private bool m_disposed; private bool m_initialized; private bool m_suppressUpdates; private Guid m_remoteCommandClientID; private Process m_remoteCommandProcess; private Ticks m_lastStatusUpdateTime; private int m_statusUpdatesDisplayed; #endregion #region [ Constructors ] /// <summary> /// Initializes a new instance of the <see cref="ServiceHelper"/> class. /// </summary> public ServiceHelper() { m_telnetSessionPassword = "s3cur3"; m_logStatusUpdates = DefaultLogStatusUpdates; m_maxStatusUpdatesLength = DefaultMaxStatusUpdatesLength; m_maxStatusUpdatesFrequency = DefaultMaxStatusUpdatesFrequency; m_monitorServiceHealth = DefaultMonitorServiceHealth; m_healthMonitorInterval = DefaultHealthMonitorInterval; m_requestHistoryLimit = DefaultRequestHistoryLimit; m_supportTelnetSessions = DefaultSupportTelnetSessions; m_supportSystemCommands = DefaultSupportSystemCommands; m_secureRemoteInteractions = DefaultSecureRemoteInteractions; m_persistSettings = DefaultPersistSettings; m_settingsCategory = DefaultSettingsCategory; m_processes = new List<ServiceProcess>(); m_remoteClients = new List<ClientInfo>(); m_clientRequestHistory = new List<ClientRequestInfo>(); m_serviceComponents = new List<object>(); m_clientRequestHandlers = new List<ClientRequestHandler>(); m_componentEnabledStates = new Dictionary<ISupportLifecycle, bool>(); // Components m_statusUpdateQueue = ProcessQueue<StatusUpdate>.CreateSynchronousQueue(ProcessStatusUpdates); m_statusUpdateQueue.Name = "StatusUpdateQueue"; m_statusUpdateQueue.ProcessException += StatusUpdateQueue_ProcessException; m_statusLog = new LogFile(); m_statusLog.FileName = "StatusLog.txt"; m_statusLog.SettingsCategory = "StatusLog"; m_statusLog.LogException += StatusLog_LogException; m_processScheduler = new ScheduleManager(); m_processScheduler.SettingsCategory = "ProcessScheduler"; m_processScheduler.ScheduleDue += Scheduler_ScheduleDue; m_errorLogger = new ErrorLogger(); m_errorLogger.ExitOnUnhandledException = false; m_errorLogger.SettingsCategory = "ErrorLogger"; m_errorLogger.ErrorLog.SettingsCategory = "ErrorLog"; m_errorLogger.LoggingException += ErrorLogger_LoggingException; } /// <summary> /// Initializes a new instance of the <see cref="ServiceHelper"/> class. /// </summary> /// <param name="container"><see cref="IContainer"/> object that contains the <see cref="ServiceHelper"/>.</param> public ServiceHelper(IContainer container) : this() { if (container != null) container.Add(this); } #endregion #region [ Properties ] /// <summary> /// Gets or sets a boolean value that indicates whether messages sent using <see cref="UpdateStatus(UpdateType,string,object[])"/> /// or <see cref="UpdateStatus(Guid,UpdateType,string,object[])"/> are to be logged to the <see cref="StatusLog"/>. /// </summary> [Category("Updates"), DefaultValue(DefaultLogStatusUpdates), Description("Indicates whether messages sent using UpdateStatus() method overloads are to be logged to the StatusLog.")] public bool LogStatusUpdates { get { return m_logStatusUpdates; } set { m_logStatusUpdates = value; } } /// <summary> /// Gets or sets the maximum numbers of characters allowed in update status messages without getting suppressed from being displayed. /// </summary> /// <exception cref="ArgumentException">The value being assigned is negative or zero.</exception> [Category("Updates"), DefaultValue(DefaultMaxStatusUpdatesLength), Description("Maximum numbers of characters allowed in update status messages without getting suppressed from being displayed.")] public int MaxStatusUpdatesLength { get { return m_maxStatusUpdatesLength; } set { if (value <= 0) throw new ArgumentException("Value must be positive"); m_maxStatusUpdatesLength = value; } } /// <summary> /// Gets or sets the maximum number of status update messages that can be issued in a second without getting suppressed from being displayed. /// </summary> /// <exception cref="ArgumentException">The value being assigned is negative or zero.</exception> [Category("Updates"), DefaultValue(DefaultMaxStatusUpdatesFrequency), Description("Maximum number of status update messages that can be issued in a second without getting suppressed from being displayed.")] public int MaxStatusUpdatesFrequency { get { return m_maxStatusUpdatesFrequency; } set { if (value <= 0) throw new ArgumentException("Value must be positive"); m_maxStatusUpdatesFrequency = value; } } /// <summary> /// Gets or sets a boolean value that indicates whether the health of the <see cref="ParentService"/> is to be monitored. /// </summary> [Category("Settings"), DefaultValue(DefaultMonitorServiceHealth), Description("Indicates whether the health of the ParentService is to be monitored.")] public bool MonitorServiceHealth { get { return m_monitorServiceHealth; } set { m_monitorServiceHealth = value; } } /// <summary>