#c# #.net-3.5 #windows-services
#c# #.net-3.5 #windows-services
Вопрос:
Я довольно новичок в работе со службами Windows, но я обнаружил необычный инцидент и хотел бы получить некоторые разъяснения. У меня есть служба Windows, написанная на C #, которую я устанавливаю и запускаю с помощью командной строки (отличные инструкции можно найти в stackoverflow). Основной метод моего сервиса выглядит следующим образом:
static void Main(string[] args)
{
if (args.Length == 0)
{
ServiceBase.Run(new MyServiceName());
}
else if (args.Length == 1)
{
const string name = "MyServiceName";
Type type = typeof(MyAssembly);
switch (args[0])
{
case "-install":
ServiceUtils.InstallService(name, type);
ServiceUtils.StartService(args, name);
break;
case "-uninstall":
ServiceUtils.StopService(name);
ServiceUtils.UninstallService(name, type);
break;
default:
throw new NotImplementedException();
}
}
}
При отладке я ВСЕГДА отправляю один параметр (-install) приложению. Из-за этого первая инструкция if (if (args.Length == 0)
НИКОГДА не выполняется. Это ожидаемо, и моя служба установлена и запущена просто отлично. Однако, если я удалю это выражение if и просто оставлю if (args.Length == 1)
инструкцию, моя служба установится правильно, но не запустится, и я получу следующую ошибку:
Не удается запустить MyServiceName на компьютере ‘.’
Мой вопрос таков: Зачем нужен код в первом операторе if, если он НИКОГДА не выполняется в моем приложении?
Вот вспомогательный код для методов InstallService и startService (который я также получил из stackoverflow):
public static void InstallService(string serviceName, Type t)
{
if (IsInstalled(serviceName)) return;
try
{
Assembly a = t.Assembly;
using (AssemblyInstaller installer = GetInstaller(a))
{
IDictionary state = new Hashtable();
try
{
installer.Install(state);
installer.Commit(state);
}
catch
{
try
{
installer.Rollback(state);
}
catch
{ }
throw;
}
}
}
catch
{
throw;
}
}
public static void StartService(string[] args, string serviceName)
{
if (!IsInstalled(serviceName)) return;
Console.WriteLine("Service is installed. Attempting to start service.");
ServiceController sc = new ServiceController();
sc.ServiceName = serviceName;
if (sc.Status == ServiceControllerStatus.Stopped)
{
Console.WriteLine("Starting {0}: ", sc.ServiceName);
try
{
sc.Start(args);
sc.WaitForStatus(ServiceControllerStatus.Running);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Ответ №1:
первый оператор if (если (аргументы.Длина == 0) НИКОГДА не выполняется
Это неверно, оно выполняется. С помощью ServiceController.Start(). Вы не можете этого увидеть, потому что контроллер службы снова запускает ваш EXE-файл, создавая другой процесс. На этот раз это сервисный процесс, а не процесс консоли. Тот, к которому у вас нет подключенного отладчика. Если вы удалите это выражение if, то служба немедленно завершит работу после начала работы. И контроллер службы правильно жалуется на это сообщением об исключении «Не удается запустить MyServiceName».
Ответ №2:
if (args.Length == 0)
{
ServiceBase.Run(new MyServiceName());
}
запускается, когда служба запускается контроллером службы, поскольку контроллер службы не передает никаких аргументов в Main().
Если вы этого не сделаете ServiceBase.Run(new MyServiceName())
, то ваша служба не будет отвечать ни на какие команды от контроллера службы, и вы получите ошибки, подобные тем, которые вы видите.
Комментарии:
1. На самом деле я запускаю ServiceController. Start() с помощью string[]. Для этого существует перегрузка. [ссылка] msdn.microsoft.com/en-us/library/9c38b683.aspx . Вы хотите сказать, что независимо от того, запускаю я свое приложение с параметром или нет, я всегда должен предоставлять точку входа в main с параметрами 0?
2. ДА. Вам нужно вызвать
ServiceBase.Run()
список служб в этом exe-файле, чтобы службы заработали, и вы не хотите вызывать его ни при каких других обстоятельствах.
Ответ №3:
Main()
по-прежнему является точкой входа приложения. Процесс запускается как отдельный шаг после запуска службы (ов) внутри.
На самом деле возможно иметь несколько служб, запущенных в одном процессе, и этот способ обработки вещей позволяет это. То есть… не просто той же самой exe-программы, но фактически в том же запущенном процессе.