Вопрос или проблема
В основном я уже пробовал принять решение, используя if else, как это:
static async Task Main(string[] args)
{
string licenseKey = Environment.GetEnvironmentVariable("LICENSE_KEY");
if (string.IsNullOrEmpty(licenseKey))
{
Console.WriteLine("LICENSE_KEY не найден.");
return;
}
if (args.Contains("--console") || Environment.GetEnvironmentVariable("RUN_AS_SERVICE") != "true")
{
Console.WriteLine("Запуск в режиме консоли.");
var cancellationTokenSource = new CancellationTokenSource();
var task = RunAsConsoleAsync(cancellationTokenSource.Token);
await task;
}
else
{
Console.WriteLine("Запуск как служба Windows.");
RunAsWindowsService();
}
}
Проблема в том, что я уже пробовал установить мой App.exe
как службу Windows. Но моя программа все еще использует первый вариант, где она работает в консоли. Если честно, я не использую переменную окружения RUN_AS_SERVICE
, потому что это было бы неэффективно для клиента в будущем.
Вот мой код для поддержки программы для работы как службы:
static void RunAsWindowsService()
{
EventLog eventLog = new EventLog();
if (!EventLog.SourceExists("TelegramBotService"))
{
EventLog.CreateEventSource("TelegramBotService", "Application");
}
eventLog.Source = "TelegramBotService";
eventLog.Log = "Application";
HostFactory.Run(x =>
{
x.Service<TelegramBotService>(s =>
{
s.ConstructUsing(name => new TelegramBotService(eventLog));
s.WhenStarted(tc =>
{
try
{
Task.Run(() => tc.StartAsync()).GetAwaiter().GetResult();
eventLog.WriteEntry("Служба успешно запущена.", EventLogEntryType.Information);
}
catch (Exception ex)
{
eventLog.WriteEntry($"Ошибка при запуске службы: {ex.Message}", EventLogEntryType.Error);
}
});
s.WhenStopped(tc =>
{
try
{
tc.Stop();
eventLog.WriteEntry("Служба успешно остановлена.", EventLogEntryType.Information);
}
catch (Exception ex)
{
eventLog.WriteEntry($"Ошибка при остановке службы: {ex.Message}", EventLogEntryType.Error);
}
});
});
x.RunAsLocalSystem();
x.SetDescription("Служба Telegram Bot");
x.SetDisplayName("TelegramBotService");
x.SetServiceName("TelegramBotService");
// Настройка автоматического запуска службы и восстанавливаемости
x.StartAutomatically();
x.EnableServiceRecovery(r => r.RestartService(1)); // Перезапуск через 1 минуту в случае ошибки
});
}
Так что, возможно, у вас есть идеи для лучшей проверки if else
? Лично я добавлю переменную окружения, если не придумаю ничего до завтра.
не важно, мой руководитель сказал мне сделать это:
static void Main(string[] args)
{
if (!Environment.UserInteractive)
{
// работа как служба
}
else
{
// работа как консольное приложение
}
}
Ответ или решение
Чтобы определить, работает ли ваше приложение как Windows-сервис или консольное приложение, вам следует использовать свойство Environment.UserInteractive
. Это свойство возвращает false
, если программа запущена как служба, и true
, если она запущена в интерактивном режиме (например, из командной строки).
Основываясь на вашем коде и комментариях, вот как вы можете реализовать это решение:
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Topshelf;
class Program
{
static async Task Main(string[] args)
{
// Получение ключа лицензии
string licenseKey = Environment.GetEnvironmentVariable("LICENSE_KEY");
if (string.IsNullOrEmpty(licenseKey))
{
Console.WriteLine("LICENSE_KEY not found.");
return;
}
// Проверка на то, как запущено приложение
if (!Environment.UserInteractive)
{
Console.WriteLine("Запуск в режиме службы.");
RunAsWindowsService();
}
else
{
Console.WriteLine("Запуск в консольном режиме.");
var cancellationTokenSource = new CancellationTokenSource();
var task = RunAsConsoleAsync(cancellationTokenSource.Token);
await task;
}
}
static async Task RunAsConsoleAsync(CancellationToken cancellationToken)
{
// Логика работы консольного приложения
Console.WriteLine("Консольное приложение запущено.");
// Имитация длительной работы
while (!cancellationToken.IsCancellationRequested)
{
await Task.Delay(1000);
Console.WriteLine("Консольное приложение работает...");
}
Console.WriteLine("Консольное приложение завершено.");
}
static void RunAsWindowsService()
{
EventLog eventLog = new EventLog();
if (!EventLog.SourceExists("TelegramBotService"))
{
EventLog.CreateEventSource("TelegramBotService", "Application");
}
eventLog.Source = "TelegramBotService";
eventLog.Log = "Application";
HostFactory.Run(x =>
{
x.Service<TelegramBotService>(s =>
{
s.ConstructUsing(name => new TelegramBotService(eventLog));
s.WhenStarted(tc =>
{
try
{
Task.Run(() => tc.StartAsync()).GetAwaiter().GetResult();
eventLog.WriteEntry("Служба успешно запущена.", EventLogEntryType.Information);
}
catch (Exception ex)
{
eventLog.WriteEntry($"Ошибка при запуске службы: {ex.Message}", EventLogEntryType.Error);
}
});
s.WhenStopped(tc =>
{
try
{
tc.Stop();
eventLog.WriteEntry("Служба успешно остановлена.", EventLogEntryType.Information);
}
catch (Exception ex)
{
eventLog.WriteEntry($"Ошибка при остановке службы: {ex.Message}", EventLogEntryType.Error);
}
});
});
x.RunAsLocalSystem();
x.SetDescription("Telegram Bot Service");
x.SetDisplayName("TelegramBotService");
x.SetServiceName("TelegramBotService");
// Настройка автоматического запуска службы и восстановления
x.StartAutomatically();
x.EnableServiceRecovery(r => r.RestartService(1)); // Перезапуск через 1 минуту в случае ошибки
});
}
}
class TelegramBotService
{
private readonly EventLog _eventLog;
public TelegramBotService(EventLog eventLog)
{
_eventLog = eventLog;
}
public Task StartAsync()
{
// Логика запуска службы
return Task.CompletedTask;
}
public void Stop()
{
// Логика остановки службы
}
}
Объяснение:
- Проверка режима выполнения: Используем
Environment.UserInteractive
для определения, запущено ли приложение как служба или консольное приложение. - Метод для консольного приложения:
RunAsConsoleAsync
содержит логику для работы в консольном режиме. - Метод для службы:
RunAsWindowsService
настраивает вашу службу с использованием библиотеки Topshelf, устанавливая необходимые обработчики событий для начала и остановки службы.
Таким образом, вы можете эффективно разделять логику для разных режимов выполнения, не полагаясь на переменные окружения.