public ApplicationService(ApplicationServiceConfig config) { _databaseName = config.DatabaseName; _schemaName = config.SchemaName; _queueName = config.QueueName; _executablePath = config.ExecutablePath; _workingDirectory = config.WorkingDirectory; _commandLineArguments = config.CommandLineArguments; _processes = new Process[config.MaxConcurrency]; _minimumConcurrency = config.MinConcurrency; }
/// <summary> /// The main entry point for the application. /// </summary> static void Main(params string[] args) { var notificationConfigs = new List <NotificationServiceConfig>(); var applicationConfigs = new List <ApplicationServiceConfig>(); try { Logger.TraceEvent(TraceEventType.Information, "Loading configuration..."); var appDirectory = System.Reflection.Assembly.GetExecutingAssembly().Location; FileInfo file = new FileInfo(appDirectory); var configPath = Path.Combine(file.Directory.Parent.FullName, @"Config\EAService.config"); var eaConfig = XElement.Load(configPath); Logger.TraceEvent(TraceEventType.Information, "Loaded config from file."); XmlNamespaceManager nsman = new XmlNamespaceManager(new NameTable()); XNamespace ea = "http://schemas.microsoft.com/sqlserver/2008/10/servicebroker/externalactivator"; nsman.AddNamespace("ea", ea.ToString()); var storedProc = eaConfig.Element(ea + "StoredProcedure").AsString(); if (string.IsNullOrWhiteSpace(storedProc)) { throw new Exception("The configuration needs to include the StoredProcedure element as a child of the Activator element."); } var notificationElements = eaConfig.XPathSelectElements("ea:NotificationServiceList/ea:NotificationService", nsman); if (notificationElements == null || !notificationElements.Any()) { throw new Exception("The EAService.config was not configured with notification services."); } foreach (var notificationElement in notificationElements) { var config = new NotificationServiceConfig() { StoredProcedure = storedProc, ConnectionString = notificationElement.XPathSelectElement("ea:ConnectionString/ea:Unencrypted", nsman).AsString() }; notificationConfigs.Add(config); } var applicationElements = eaConfig.XPathSelectElements("ea:ApplicationServiceList/ea:ApplicationService", nsman); if (applicationElements == null || !applicationElements.Any()) { throw new Exception("The EAService.config was not configured with application services."); } foreach (var applicationElement in applicationElements) { string maxConcVal = applicationElement.XPathSelectElement("ea:Concurrency", nsman)?.Attribute("max")?.Value; string minConcVal = applicationElement.XPathSelectElement("ea:Concurrency", nsman)?.Attribute("min")?.Value; int maxConc = int.TryParse(maxConcVal, out maxConc) ? Math.Max(maxConc, 0) : 0; int minConc = int.TryParse(minConcVal, out minConc) ? Math.Max(minConc, 0) : 0; var config = new ApplicationServiceConfig() { DatabaseName = applicationElement.XPathSelectElement("ea:OnNotification/ea:DatabaseName", nsman).AsString(), SchemaName = applicationElement.XPathSelectElement("ea:OnNotification/ea:SchemaName", nsman).AsString(), QueueName = applicationElement.XPathSelectElement("ea:OnNotification/ea:QueueName", nsman).AsString(), ExecutablePath = applicationElement.XPathSelectElement("ea:LaunchInfo/ea:ImagePath", nsman).AsString(), WorkingDirectory = applicationElement.XPathSelectElement("ea:LaunchInfo/ea:WorkDir", nsman).AsString(), CommandLineArguments = applicationElement.XPathSelectElement("ea:LaunchInfo/ea:CmdLineArgs", nsman).AsString(), MaxConcurrency = maxConc, MinConcurrency = minConc }; applicationConfigs.Add(config); } Logger.TraceEvent(TraceEventType.Information, "Configuration parsed successfully."); } catch (Exception ex) { Logger.TraceEvent(TraceEventType.Error, $"{ex}"); throw ex; } CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); var applicationServiceList = new ApplicationServiceList(applicationConfigs); var tasks = notificationConfigs .Select(c => new NotificationService(c, applicationServiceList)) .SelectMany(n => new [] { new Task(() => n.Execute(cancellationTokenSource.Token), TaskCreationOptions.LongRunning), new Task(() => n.MonitorQueueReaders(cancellationTokenSource.Token), TaskCreationOptions.LongRunning) }) .ToArray(); if (args.Length > 0 && args[0].StartsWith("/service:", StringComparison.OrdinalIgnoreCase)) { var argParts = args[0].Split(':'); if (argParts.Length != 2) { throw new InvalidOperationException($"Invalid argument '{args[0]}'. Expected /service:<serviceName>"); } ExecuteAsWindowsService(tasks, cancellationTokenSource, argParts[1]); } else { ExecuteAsConsoleApplication(tasks, cancellationTokenSource); } }