//******************************************************************************************************
// 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.Reflection;
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 ]
///
/// Indicates the state of a Windows Service.
///
public enum ServiceState
{
///
/// Service has started.
///
Started,
///
/// Service has stopped.
///
Stopped,
///
/// Service has paused.
///
Paused,
///
/// Service has resumed.
///
Resumed,
///
/// Service has shutdown.
///
Shutdown
}
#endregion
///
/// Component that provides added functionality to a Windows Service.
///
///
///
///
///
///
[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
///
/// Specifies the default value for the property.
///
public const bool DefaultLogStatusUpdates = true;
///
/// Specifies the default value for the property.
///
public const int DefaultMaxStatusUpdatesLength = 8192;
///
/// Specifies the default value for the property.
///
public const int DefaultMaxStatusUpdatesFrequency = 30;
///
/// Specifies the default value for the property.
///
public const bool DefaultMonitorServiceHealth = false;
///
/// Specifies the default value for the property.
///
public const double DefaultHealthMonitorInterval = 5.0D;
///
/// Specifies the default value for the property.
///
public const int DefaultRequestHistoryLimit = 50;
///
/// Specifies the default value for the property.
///
public const bool DefaultSupportTelnetSessions = false;
///
/// Specifies the default value for the property.
///
public const bool DefaultSupportSystemCommands = false;
///
/// Specifies the default value for the property.
///
public const bool DefaultSecureRemoteInteractions = false;
///
/// Specifies the default value for the property.
///
public const bool DefaultPersistSettings = false;
///
/// Specifies the default value for the property.
///
public const string DefaultSettingsCategory = "ServiceHelper";
// Events
///
/// Occurs when the is starting.
///
[Category("Service"),
Description("Occurs when the ParentService is starting.")]
public event EventHandler> ServiceStarting;
///
/// Occurs when the has started.
///
[Category("Service"),
Description("Occurs when the ParentService has started.")]
public event EventHandler ServiceStarted;
///
/// Occurs when the is stopping.
///
[Category("Service"),
Description("Occurs when the ParentService is stopping.")]
public event EventHandler ServiceStopping;
///
/// Occurs when the has stopped.
///
[Category("Service"),
Description("Occurs when the ParentService has stopped.")]
public event EventHandler ServiceStopped;
///
/// Occurs when the is pausing.
///
[Category("Service"),
Description("Occurs when the ParentService is pausing.")]
public event EventHandler ServicePausing;
///
/// Occurs when the has paused.
///
[Category("Service"),
Description("Occurs when the ParentService has paused.")]
public event EventHandler ServicePaused;
///
/// Occurs when the is resuming.
///
[Category("Service"),
Description("Occurs when the ParentService is resuming.")]
public event EventHandler ServiceResuming;
///
/// Occurs when the has resumed.
///
[Category("Service"),
Description("Occurs when the ParentService has resumed.")]
public event EventHandler ServiceResumed;
///
/// Occurs when the system is being shutdown.
///
[Category("System"),
Description("Occurs when the system is being shutdown.")]
public event EventHandler SystemShutdown;
///
/// Occurs when a request is received from one of the .
///
///
/// is the ID of the remote client that sent the request.
/// is the sent by the remote client.
///
[Category("Client"),
Description("Occurs when a request is received from one of the RemoteClients.")]
public event EventHandler> ReceivedClientRequest;
///
/// Occurs when the state of a defiend changes.
///
///
/// is the .
/// is the
///
[Category("Process"),
Description("Occurs when the state of a defiend ServiceProcess changes.")]
public event EventHandler> 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 m_processes;
private readonly List