Для второй части Вашего вопроса, я думал об этом, и вот это класс, я ставлю вместе, что помогает создать службу, которая может быть запущена как в консоли приложения, а также службы Windows. Это свежо с прессой, поэтому могут возникнуть некоторые проблемы для решения, и некоторые рефакторинги требуют esp. вокруг кода отражения.
NB: Вы должны установить тип вывода Сервисного проекта на Console Application
, это будет работать нормально как обычное обслуживание.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.ServiceProcess;
using System.Threading;
namespace DotNetWarrior.ServiceProcess
{
public class ServiceManager
{
private List<ServiceBase> _services = new List<ServiceBase>();
public void RegisterService(ServiceBase service)
{
if (service == null) throw new ArgumentNullException("service");
_services.Add(service);
}
public void Start(string[] args)
{
if (Environment.UserInteractive)
{
foreach (ServiceBase service in _services)
{
Start(service, args);
}
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
Thread.Sleep(Timeout.Infinite);
}
else
{
ServiceBase.Run(_services.ToArray());
}
}
public void Stop()
{
foreach (ServiceBase service in _services)
{
Stop(service);
}
}
private void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Stop();
Environment.Exit(0);
}
private void Start(ServiceBase service, string[] args)
{
try
{
Type serviceType = typeof(ServiceBase);
MethodInfo onStartMethod = serviceType.GetMethod(
"OnStart",
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new Type[] { typeof(string[]) },
null);
if (onStartMethod == null)
{
throw new Exception("Could not locate OnStart");
}
Console.WriteLine("Starting Service: {0}", service.ServiceName);
onStartMethod.Invoke(service, new object[] { args });
Console.WriteLine("Started Service: {0}", service.ServiceName);
}
catch (Exception ex)
{
Console.WriteLine("Start Service Failed: {0} - {1}", service.ServiceName, ex.Message);
}
}
private void Stop(ServiceBase service)
{
try
{
Type serviceType = typeof(ServiceBase);
MethodInfo onStopMethod = serviceType.GetMethod(
"OnStop",
BindingFlags.NonPublic | BindingFlags.Instance);
if (onStopMethod == null)
{
throw new Exception("Could not locate OnStart");
}
Console.WriteLine("Stoping Service: {0}", service.ServiceName);
onStopMethod.Invoke(service, null);
Console.WriteLine("Stopped Service: {0}", service.ServiceName);
}
catch (Exception ex)
{
Console.WriteLine("Stop Service Failed: {0} - {1}", service.ServiceName, ex.Message);
}
}
}
}
Чтобы использовать эту функцию, вы можете копировать стандартный код из точки входа Main
службы и заменить его следующим образом.
static void Main(string[] args)
{
ServiceManager services = new ServiceManager();
services.RegisterService(new Service1());
services.Start(args);
}
Метод services.Start()
обнаружит, что служба в настоящее время работает как интерактивное приложение и вручную вызвать OnStart метод всех зарегистрированных услуг, после начала основной поток переходит в спящий режим. Чтобы остановить службы, просто нажмите «Ctrl + C», что приведет к остановке Сервисов, вызвав метод OnStop службы.
Конечно, приложение запускается службой SCM, а затем все работает как обычный сервис. Единственное предостережение заключается в том, что служба не должна запускаться с «Разрешить службе взаимодействовать с рабочим столом», поскольку это приведет к тому, что служба будет запущена в интерактивном режиме, даже если она запущена как служба. Это можно обойти, если это необходимо, но эй, я только что написал код.
Мониторинг и запуск/остановка службы
Из командной строки можно использовать net.exe Пуск/Остановка службы
Start a service
net start <service name>
Stop a service
net stop <service name>
Для управления службы из .NET вы можете использовать System.ServiceProcess.ServiceController
// Stop a service
System.ServiceProcess.ServiceController sc = new
System.ServiceProcess.ServiceController("<service name>");
sc.Stop();
Для общего общения с сервисом, кроме того, что обеспечивается за счет ServiceController Я предлагаю вам разместить службу WCF как часть вашей службы, которую вы затем можете использовать для связи с сервисом для запроса внутренних данных, специфичных для вашей службы.
Обработка Scheduling
Честно говоря, я был колеблющимся, чтобы ответить на этот аспект вопроса, поскольку существует так много подходов, каждый с там Pros/Cons. Поэтому я просто дам вам несколько вариантов высокого уровня. Вероятно, вы уже это продумали, но вот несколько вещей с моей головы
Если вы используете SQL Server для хранения уведомлений.
Имейте SP, который вы можете вызвать, чтобы получить напоминания, которые подлежат оплате, а затем обработать результат, чтобы поднять напоминания надлежащим образом.
С этой SP у вас есть некоторые варианты
- Вызвать SP периодически от службы и обрабатывать напоминания
- Have в SQL Работа, которая периодически запускает SP и добавляет напоминание к Service Broker Queue. Затем ваша служба может подписаться на очередь и обрабатывать напоминания, как они появляются в очереди. Преимущество этого подхода заключается в том, что вы можете масштабировать работу с несколькими серверами, обрабатывая генерацию уведомлений напоминания без какого-либо специального кодирования, просто добавьте еще один сервер, на котором выполняется ваша служба, и сообщения будут автоматически распределены между двумя серверами.
Если вы не используете SQL Server для хранения напоминаний
Вы все еще можете использовать подобный подход, как для SQL Server. Конечно, служба Windows может запросить хранилище данных, используя то, что когда-либо было одобрено и обрабатывает напоминания.Получение этого масштаба немного сложнее, так как вам нужно будет убедиться, что несколько серверов не обрабатывают одно и то же напоминание и т. Д., Но не разбивают поезд.
Я думаю, что он покрывает суть этого, все остальное имеет некоторые отличия от вышеизложенного. В конечном итоге ваше решение будет зависеть от целевых объемов, требований надежности и т. Д.
@Chris Спасибо за обмен кодом, я надеялся использовать консольное приложение в качестве монитора для работы службы Windows, с которой я мог бы начать и остановить любой момент, чтобы «прослушивать». Однако вы не будете потрачены впустую, так как он пригодится для чего-то еще, что я хотел сделать =) Спасибо, что вам нужна помощь. –
@Wayne, извините, я полностью пропустил точку там. См. Обновленное обновление. –
@Chris Спасибо за обновление, у вас есть какие-либо ссылки или код для размещения службы WCF, поэтому я могу получить внутренний статус. Основная идея заключалась в том, чтобы иметь возможность запускать приложение, чтобы точно видеть, что служба выполняла в любой момент времени, например. Обработка сообщения 1 из 2 и т.д. –