Определение запуска программы в качестве службы Windows / консольной команды C# .NET

Вопрос или проблема

В основном я уже пробовал принять решение, используя 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()
    {
        // Логика остановки службы
    }
}

Объяснение:

  1. Проверка режима выполнения: Используем Environment.UserInteractive для определения, запущено ли приложение как служба или консольное приложение.
  2. Метод для консольного приложения: RunAsConsoleAsync содержит логику для работы в консольном режиме.
  3. Метод для службы: RunAsWindowsService настраивает вашу службу с использованием библиотеки Topshelf, устанавливая необходимые обработчики событий для начала и остановки службы.

Таким образом, вы можете эффективно разделять логику для разных режимов выполнения, не полагаясь на переменные окружения.

Оцените материал
Добавить комментарий

Капча загружается...