/base/Applications/ServiceManager/SMSClient/SMSClient.cs
C# | 892 lines | 697 code | 182 blank | 13 comment | 99 complexity | 51fb7ee922ba130f09374531c6bd8feb MD5 | raw file
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Microsoft Research Singularity
- //
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //
- // Note: Service Manager client program
- //
- using System;
- using System.Threading;
-
- using Microsoft.SingSharp;
- using Microsoft.SingSharp.Reflection;
- using Microsoft.Singularity;
- using Microsoft.Singularity.Applications;
- using Microsoft.Singularity.Channels;
- using Microsoft.Singularity.Configuration;
- using Microsoft.Singularity.Contracts;
- using Microsoft.Singularity.Directory;
- using Microsoft.Singularity.Io;
- using Microsoft.Singularity.ServiceManager;
- [assembly: Transform(typeof(ApplicationResourceTransform))]
-
- namespace Microsoft.Singularity.Applications.ServiceManager
- {
- [ConsoleCategory(HelpMessage="Service management client", DefaultAction=true)]
- internal class DefaultConfig
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- reflective internal DefaultConfig();
-
- internal int AppMain()
- {
- Console.WriteLine("Use -? for help.");
- return 0;
- }
- }
-
- [ConsoleCategory(Action="start", HelpMessage="Start a service")]
- internal class StartConfig
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Mandatory=true, Position=0)]
- internal string serviceName;
-
- // [BoolParameter("w", Mandatory=false, HelpMessage="Wait for service to start.")]
- public bool wait;
-
- reflective internal StartConfig();
-
- internal int AppMain()
- {
- return SMSClient.StartService((!)serviceName, wait);
- }
- }
-
- [ConsoleCategory(Action="stop", HelpMessage="Stop a service")]
- internal class StopServiceCommand
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Mandatory=true, Position=0)]
- internal string serviceName;
-
- // [BoolParameter("w", Mandatory=false, HelpMessage="Wait for service to stop.")]
- public bool wait;
-
- reflective internal StopServiceCommand();
-
- internal int AppMain()
- {
- return SMSClient.StopService((!)serviceName, wait);
- }
- }
-
- [ConsoleCategory(Action="list", HelpMessage="Show a list of services")]
- internal class ListConfig
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- reflective internal ListConfig();
-
- internal int AppMain()
- {
- return SMSClient.ListServices(this);
- }
- }
-
- [ConsoleCategory(Action="show", HelpMessage="Show details about a specific service.")]
- internal class ShowServiceParameters
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Position=0, Mandatory=true, HelpMessage="The service to examine.")]
- public string ServiceName;
-
- reflective internal ShowServiceParameters();
-
- internal int AppMain()
- {
- if (ServiceName == null) {
- Console.WriteLine("The 'service' parameter is required, but has not been provided.");
- return -1;
- }
-
- ServiceManagerContract.Imp! svmanager = SMSClient.ConnectServiceManager();
- try {
- ServiceError error = SMSClient.SelectService(svmanager, this.ServiceName);
- if (error != ServiceError.None)
- return -1;
-
- bool errors = false;
-
- svmanager.SendQueryServiceConfig();
- switch receive {
- case svmanager.CurrentServiceConfig(config):
- SMSClient.ShowConfigDetailed(config);
- config.Dispose();
- break;
-
- case svmanager.RequestFailed(err):
- if (err == ServiceError.ServiceNotFound) {
- Console.WriteLine("There is no service with name '{0}'.", this.ServiceName);
- return -1;
- }
-
- Console.WriteLine("Failed to query service configuration.");
- SMSClient.ShowServiceError(err);
- errors = true;
- break;
-
- case svmanager.ChannelClosed():
- Console.WriteLine("The Service Manager closed its channel unexpectedly.");
- return -1;
- }
-
- svmanager.SendQueryServiceStatus();
- switch receive {
- case svmanager.CurrentServiceStatus(status):
- Console.WriteLine();
- SMSClient.ShowStatusDetailed(status);
- status.Dispose();
- break;
-
- case svmanager.RequestFailed(err):
- Console.WriteLine("Failed to query service status.");
- SMSClient.ShowServiceError(err);
- errors = true;
- break;
-
- case svmanager.ChannelClosed():
- Console.WriteLine("The Service Manager closed its channel unexpectedly.");
- return -1;
- }
-
- if (errors)
- return -1;
- else
- return 0;
-
- }
- finally {
- delete svmanager;
- }
- }
- }
-
- [ConsoleCategory(Action="watch", HelpMessage="Watch the status of a service")]
- internal class WatchConfig
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Mandatory=true, Position=0)]
- internal string serviceName;
-
- reflective internal WatchConfig();
-
- internal int AppMain()
- {
- return SMSClient.WatchService((!)serviceName);
- }
- }
-
- [ConsoleCategory(Action="watchall", HelpMessage="Watch the status of the Service Manager")]
- internal class WatchAllConfig
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- #if false
- [BoolParameter("c", Mandatory=false, HelpMessage="Watch all service configuration changes")]
- public bool watchConfigChanges;
-
- [BoolParameter("s", Mandatory=false, HelpMessage="Watch all service status changes")]
- public bool watchStatusChanges;
- #endif
-
- reflective internal WatchAllConfig();
-
- internal int AppMain()
- {
- #if false
- ServiceManagerEventMask desiredEvents = 0;
-
- if (watchConfigChanges)
- desiredEvents |= ServiceManagerEventMask.AnyServiceConfig;
-
- if (watchStatusChanges)
- desiredEvents |= ServiceManagerEventMask.AnyServiceStatus;
-
- if (desiredEvents == 0)
- desiredEvents = ServiceManagerEventMask.AnyServiceConfig | ServiceManagerEventMask.AnyServiceStatus;
- #else
- ServiceManagerEventMask desiredEvents = ServiceManagerEventMask.AnyServiceConfig | ServiceManagerEventMask.AnyServiceStatus;
- #endif
-
- ServiceManagerContract.Imp! svmanager = SMSClient.ConnectServiceManager();
-
- svmanager.SendWatchServiceManager(desiredEvents);
-
- switch receive {
- case svmanager.Ok():
- break;
-
- case svmanager.RequestFailed(error):
- Console.WriteLine("The Service Manager rejected the subscription request.");
- SMSClient.ShowServiceError(error);
- delete svmanager;
- return -1;
- }
-
- Console.WriteLine("Watching Service Manager...");
-
- for (;;) {
- Console.WriteLine("Sending WaitNextServiceManagerChange");
- svmanager.SendWaitNextServiceManagerChange();
-
- Console.WriteLine("switch-receive");
-
- switch receive {
- case svmanager.ServiceManagerChanged(events):
- Console.WriteLine("Service Manager events fired: {0:x8}", ((uint)events));
- break;
- }
- }
- }
- }
-
- [ConsoleCategory(Action="create", HelpMessage="Create a new service entry")]
- internal class CreateServiceCommand
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Mandatory=true, Position=0)]
- internal string serviceName;
-
- [StringParameter("exe", Mandatory=false, HelpMessage="Executable to use; if omitted, uses service name.")]
- public string executableName;
-
- [StringParameter("display", Mandatory=false, HelpMessage="Display name to use; if omitted, uses service name.")]
- public string displayName;
-
- [BoolParameter("disabled", Mandatory=false, HelpMessage="Create in a disabled state.")]
- public bool isAdministrativelyDisabled;
-
- reflective internal CreateServiceCommand();
-
- internal int AppMain()
- {
- assert serviceName != null;
- if (serviceName.Length == 0) {
- Console.WriteLine("Invalid service name.");
- return -1;
- }
-
- if (executableName == null || executableName.Length == 0)
- executableName = serviceName;
-
- if (displayName == null || displayName.Length == 0)
- displayName = serviceName;
-
- ServiceManagerContract.Imp! svmanager = SMSClient.ConnectServiceManager();
- try {
-
- ServiceConfig config = new ServiceConfig();
- config.ServiceName = Bitter.FromString2(serviceName);
- config.ExecutableName = Bitter.FromString2(executableName);
- config.DisplayName = Bitter.FromString2(displayName);
- config.IsAdministrativelyDisabled = isAdministrativelyDisabled;
- config.MinProcesses = 0;
- config.MaxProcesses = 1;
- config.MaxClientsPerProcess = ServiceConfig.UnlimitedClientsPerProcess;
- config.MaxProcessAgeInSeconds = ServiceConfig.UnlimitedProcessAge;
-
- svmanager.SendCreateService(config);
-
- switch receive {
- case svmanager.Ok():
- Console.WriteLine("Service was successfully created.");
- return 0;
-
- case svmanager.RequestFailed(error):
- Console.WriteLine("Failed to create service.");
- SMSClient.ShowServiceError(error);
- return -1;
- }
-
- }
- finally {
- delete svmanager;
- }
- }
- }
-
- [ConsoleCategory(Action="delete", HelpMessage="Delete an existing service")]
- internal class DeleteServiceCommand
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Mandatory=true, Position=0)]
- internal string serviceName;
-
- reflective internal DeleteServiceCommand();
-
- internal int AppMain()
- {
- assert serviceName != null;
- if (serviceName.Length == 0) {
- Console.WriteLine("Invalid service name.");
- return -1;
- }
-
- ServiceManagerContract.Imp! svmanager = SMSClient.ConnectServiceManager();
- try {
-
- ServiceError error = SMSClient.SelectService(svmanager, serviceName);
- if (error != ServiceError.None)
- return -1;
-
- svmanager.SendDeleteService();
-
- switch receive {
- case svmanager.Ok():
- Console.WriteLine("Service was successfully deleted.");
- return 0;
-
- case svmanager.RequestFailed(err):
- Console.WriteLine("Failed to delete service.");
- SMSClient.ShowServiceError(err);
- return -1;
- }
-
- }
- finally {
- delete svmanager;
- }
- }
- }
-
- [ConsoleCategory(Action="enable", HelpMessage="Enable a service")]
- internal class EnableServiceCommand
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Mandatory=true, Position=0)]
- internal string serviceName;
-
- reflective internal EnableServiceCommand();
-
- internal int AppMain()
- {
- assert serviceName != null;
- if (serviceName.Length == 0) {
- Console.WriteLine("Invalid service name.");
- return -1;
- }
-
- ServiceManagerContract.Imp! svmanager = SMSClient.ConnectServiceManager();
- try {
-
- ServiceError error = SMSClient.SelectService(svmanager, serviceName);
- if (error != ServiceError.None)
- return -1;
-
- svmanager.SendEnableService(true);
-
- switch receive {
- case svmanager.Ok():
- Console.WriteLine("Service was successfully enabled.");
- return 0;
-
- case svmanager.RequestFailed(err):
- Console.WriteLine("Failed to enable service.");
- SMSClient.ShowServiceError(err);
- return -1;
- }
-
- }
- finally {
- delete svmanager;
- }
- }
- }
-
- [ConsoleCategory(Action="disable", HelpMessage="Disable a service")]
- internal class DisableServiceCommand
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Mandatory=true, Position=0)]
- internal string serviceName;
-
- reflective internal DisableServiceCommand();
-
- internal int AppMain()
- {
- assert serviceName != null;
- if (serviceName.Length == 0) {
- Console.WriteLine("Invalid service name.");
- return -1;
- }
-
- ServiceManagerContract.Imp! svmanager = SMSClient.ConnectServiceManager();
- try {
-
- ServiceError error = SMSClient.SelectService(svmanager, serviceName);
- if (error != ServiceError.None)
- return -1;
-
- svmanager.SendEnableService(false);
-
- switch receive {
- case svmanager.Ok():
- Console.WriteLine("Service was successfully disabled.");
- return 0;
-
- case svmanager.RequestFailed(err):
- Console.WriteLine("Failed to disable service.");
- SMSClient.ShowServiceError(err);
- return -1;
- }
-
- }
- finally {
- delete svmanager;
- }
- }
- }
-
- [ConsoleCategory(Action="kill", HelpMessage="Terminate the process(es) of a service.")]
- internal class TerminateServiceCommand
- {
- [InputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Exp:READY> Stdin;
-
- [OutputEndpoint("data")]
- public readonly TRef<UnicodePipeContract.Imp:READY> Stdout;
-
- [StringParameter("service", Mandatory=true, Position=0)]
- internal string serviceName;
-
- [LongParameter("pid", Mandatory=false, Position=1, Default=-1)]
- internal long processId;
-
- reflective internal TerminateServiceCommand();
-
- internal int AppMain()
- {
- assert serviceName != null;
- if (serviceName.Length == 0) {
- Console.WriteLine("Invalid service name.");
- return -1;
- }
-
- ServiceManagerContract.Imp! svmanager = SMSClient.ConnectServiceManager();
- try {
-
- ServiceError error = SMSClient.SelectService(svmanager, serviceName);
- if (error != ServiceError.None)
- return -1;
-
- if (processId != -1)
- svmanager.SendTerminateServiceProcess((int)processId);
- else
- svmanager.SendTerminateServiceAllProcesses();
-
- switch receive {
- case svmanager.Ok():
- return 0;
-
- case svmanager.RequestFailed(err):
- SMSClient.ShowServiceError(err);
- return -1;
- }
-
- }
- finally {
- delete svmanager;
- }
- }
- }
-
-
- public class SMSClient
- {
- internal static ServiceManagerContract.Imp! ConnectServiceManager()
- {
- using (ImpatientWatcher watcher = new ImpatientWatcher("ConnectServiceManager", "create channel", 250)) {
- ErrorCode error;
- ServiceManagerContract.Imp! manager_imp;
- ServiceManagerContract.Exp! manager_exp;
- ServiceManagerContract.NewChannel(out manager_imp, out manager_exp);
-
- watcher.NextStep("NewClientEndpoint", 250);
-
- DirectoryServiceContract.Imp! rootds = DirectoryService.NewClientEndpoint();
- try {
- watcher.NextStep("SdsUtils.Bind", 1000);
- if (SdsUtils.Bind(ServiceManagerContract.ModuleName, rootds, manager_exp, out error)) {
- watcher.NextStep("RecvSuccess", 250);
- manager_imp.RecvSuccess();
- return manager_imp;
- }
- else {
- delete manager_imp;
- Console.WriteLine("Failed to contact the Service Manager. Error: " + SdsUtils.ErrorCodeToString(error));
- throw new Exception("Failed to connect to Service Manager.");
- }
- }
- finally {
- delete rootds;
- }
- }
- }
-
- internal static ServiceError SelectService(ServiceManagerContract.Imp! svmanager, string! serviceName)
- {
- svmanager.SendSelectService(Bitter.FromString2(serviceName));
- switch receive {
- case svmanager.Ok():
- // Console.WriteLine("Successfully selected service '{0}'.", serviceName);
- return ServiceError.None;
-
- case svmanager.RequestFailed(error):
- Console.WriteLine("Failed to select service '{0}'.", serviceName);
- ShowServiceError(error);
- return error;
-
- case svmanager.ChannelClosed():
- throw new Exception("Service Manager closed channel before responding.");
- }
- }
-
- internal static void ShowServiceError(ServiceError error)
- {
- Console.WriteLine("ServiceError: " + ServiceEnums.ToString(error));
- }
-
- static internal int StartService(string! serviceName, bool wait)
- {
- ServiceManagerContract.Imp! svmanager = ConnectServiceManager();
-
- try {
-
- ServiceError error = SelectService(svmanager, serviceName);
- if (error != ServiceError.None) {
- return -1;
- }
-
- if (wait) {
- svmanager.SendStartServiceWait();
-
- for (;;) {
- switch receive {
- case svmanager.RequestFailed(err):
- ShowServiceError(err);
- return -1;
-
- case svmanager.ServiceStarting():
- Console.WriteLine("Service Manager accepted request to start service '{0}'.", serviceName);
- return 0;
-
- case timeout(TimeSpan.FromSeconds(10)):
- Console.WriteLine("waiting...");
- break;
- }
- }
- }
- else {
- svmanager.SendStartServiceNoWait();
-
- switch receive {
- case svmanager.RequestFailed(err):
- ShowServiceError(err);
- return -1;
-
- case svmanager.ServiceStarting():
- Console.WriteLine("Service Manager accepted request to start service '{0}'.", serviceName);
- return 0;
- }
- }
- }
- finally {
- delete svmanager;
- }
- }
-
- internal static int StopService(string! serviceName, bool wait)
- {
- ServiceManagerContract.Imp! svmanager = ConnectServiceManager();
-
- try {
-
- ServiceError error = SelectService(svmanager, serviceName);
- if (error != ServiceError.None)
- return -1;
-
- if (wait) {
- svmanager.SendStopServiceWait();
-
- for (;;) {
- switch receive {
- case svmanager.RequestFailed(err):
- ShowServiceError(err);
- if (err == ServiceError.CannotStopService) {
- Console.WriteLine("If this service is an 'always active' service, then the stop command cannot be used.");
- Console.WriteLine("Instead, use the 'disable' command.");
- }
- return -1;
-
- case svmanager.ServiceStopping():
- Console.WriteLine("Service Manager accepted request to stop service '{0}'.", serviceName);
- return 0;
-
- case timeout(TimeSpan.FromSeconds(10)):
- Console.WriteLine("waiting...");
- break;
- }
- }
- }
- else {
- svmanager.SendStopServiceNoWait();
-
- switch receive {
- case svmanager.RequestFailed(err):
- ShowServiceError(err);
- return -1;
-
- case svmanager.ServiceStopping():
- Console.WriteLine("Service Manager accepted request to stop service '{0}'.", serviceName);
- return 0;
- }
- }
- }
- finally {
- delete svmanager;
- }
- }
-
- internal static int WatchService(string! serviceName)
- {
- ServiceManagerContract.Imp! svmanager = ConnectServiceManager();
-
- try {
-
- ServiceError error = SelectService(svmanager, serviceName);
- if (error != ServiceError.None) {
- return -1;
- }
-
- svmanager.SendWatchServiceStatus();
-
- switch receive {
- case svmanager.RequestFailed(err):
- ShowServiceError(err);
- return -1;
-
- case svmanager.Ok():
- Console.WriteLine("Service Manager accepted request to watch service '{0}'.", serviceName);
- break;
- }
-
- for (;;) {
- svmanager.SendWaitServiceChange();
-
- switch receive {
- case svmanager.ServiceStatusChanged(ServiceStatus status, bool missedChange):
- Console.WriteLine("Status changed: ");
- Console.WriteLine(" State: " + ServiceEnums.ToString(status.State));
- if (missedChange) {
- Console.WriteLine(" Note: At least one status change was missed.");
- }
- break;
-
- case svmanager.RequestFailed(err):
- Console.WriteLine("Request failed.");
- ShowServiceError(err);
- return -1;
-
- case svmanager.ChannelClosed():
- Console.WriteLine("Service Manager closed channel!");
- return -1;
- }
- }
-
- }
- finally {
- delete svmanager;
- }
- }
-
- const string ListServiceFormat = "{0,-20} {1,-10} {2,-6} {3}";
-
- internal static int ListServices(ListConfig! config)
- {
- ServiceManagerContract.Imp! svmanager = ConnectServiceManager();
-
-
- try {
- Console.WriteLine(ListServiceFormat, "Name", "State", "PID", "Display Name");
- Console.WriteLine(ListServiceFormat,
- new String('-', 20),
- new String('-', 10),
- new String('-', 6),
- new String('-', 30));
-
- ServiceInfo[]! in ExHeap first_entries = new[ExHeap] ServiceInfo[40];
- svmanager.SendEnumerateServices(first_entries);
-
- for (;;) {
- switch receive {
- case svmanager.EnumerationTerminated(entries, count):
- ListServices(entries, count);
- delete entries;
- return 0;
-
- case svmanager.NextServiceInfo(entries, count):
- ListServices(entries, count);
- svmanager.SendEnumerateServices(entries);
- break;
-
- case svmanager.ChannelClosed():
- Console.WriteLine("Service Manager channel closed");
- return -1;
-
- }
- }
- }
- finally {
- delete svmanager;
- }
- }
-
- static void ListServices(ServiceInfo[]! in ExHeap entries, int count)
- {
- for (int i = 0; i < count; i++) {
- expose(entries[i])
- {
- string! serviceName = ToString(entries[i].Config.ServiceName);
- string! displayName = ToString(entries[i].Config.DisplayName);
- string! stateString = ServiceEnums.ToString(entries[i].Status.State);
- string! processIdString = entries[i].Status.ProcessId != -1 ?
- (!)entries[i].Status.ProcessId.ToString() : "";
- Console.WriteLine(ListServiceFormat, serviceName, stateString, processIdString, displayName);
- }
- }
- }
-
- public static string! ToString(char[] in ExHeap str)
- {
- if (str != null)
- return Bitter.ToString2(str);
- else
- return "";
- }
-
- public static void ShowConfigDetailed(ServiceConfig config)
- {
- if (config.ServiceName == null) {
- Console.WriteLine("Error: A ServiceConfig structure had a null ServiceName field.");
- return;
- }
- string! serviceName = Bitter.ToString2(config.ServiceName);
-
- string! executableName = config.ExecutableName != null ? Bitter.ToString2(config.ExecutableName) : "";
- string! displayName = config.DisplayName != null ? Bitter.ToString2(config.DisplayName) : "";
-
- Console.WriteLine("Service Configuration");
- Console.WriteLine("---------------------");
- Console.WriteLine();
- Console.WriteLine(DetailFormat, "Service Name", serviceName);
- Console.WriteLine(DetailFormat, "Executable", executableName);
- Console.WriteLine(DetailFormat, "Display Name", displayName);
- Console.WriteLine(DetailFormat, "Activation Mode", ServiceEnums.ToString(config.ActivationMode));
- Console.WriteLine(DetailFormat, "Is Disabled?", config.IsAdministrativelyDisabled.ToString());
-
- Console.WriteLine(DetailFormat, "Min/Max Processes", String.Format("min {0} / {1}",
- config.MinProcesses,
- config.MaxProcesses == ServiceConfig.UnlimitedProcesses ? "no max" : "max " + config.MaxProcesses));
-
- string! max_age_text;
- if (config.MaxProcessAgeInSeconds == ServiceConfig.UnlimitedProcessAge)
- max_age_text = "unlimited";
- else {
- TimeSpan limit = TimeSpan.FromSeconds(config.MaxProcessAgeInSeconds);
- max_age_text = (!)limit.ToString();
- }
- Console.WriteLine(DetailFormat, "Max Process Age", max_age_text);
-
- string clients_per_process_text;
- if (config.MaxClientsPerProcess == ServiceConfig.UnlimitedClientsPerProcess) {
- clients_per_process_text = "unlimited";
- }
- else {
- clients_per_process_text = config.MaxClientsPerProcess.ToString();
- }
- Console.WriteLine(DetailFormat, "Max Clients per Process", clients_per_process_text);
-
- }
-
- const string DetailFormat = "{0,-25}: {1}";
-
- public static void ShowStatusDetailed(ServiceStatus status)
- {
- Console.WriteLine("Service Status");
- Console.WriteLine("--------------");
- Console.WriteLine();
- Console.WriteLine(DetailFormat, "State", ServiceEnums.ToString(status.State));
- if (status.State != ServiceState.Stopped) {
- Console.WriteLine(DetailFormat, "Process ID", status.ProcessId);
- }
-
- // This is not yet accurate.
- // Console.WriteLine(DetailFormat, "Total Active Clients", status.TotalActiveClients);
-
- Console.WriteLine(DetailFormat, "Total Active Processes", status.TotalActiveProcesses);
- Console.WriteLine(DetailFormat, "Connect Queue Length", status.ConnectQueueLength);
-
- Console.WriteLine(DetailFormat, "Last Process Start", status.LastStartFailed ? "FAILED" : "Succeeded");
- if (status.LastStartFailed) {
- Console.WriteLine(DetailFormat, "Last Start Error", ServiceEnums.ToString(status.LastStartError));
- }
- }
- }
-
- }
-