You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# .NET程序Windows服务/控制台运行的判断逻辑优化问询

问题描述

我已基于C# .NET实现了程序在控制台与Windows服务两种模式下运行的逻辑,通过命令行参数和环境变量进行判断。但将App.exe安装为Windows服务后,程序仍以控制台模式启动,且我不想使用RUN_AS_SERVICE环境变量(不利于后续客户端部署),现寻求更优的if else判断方案。

现有代码

判断逻辑代码

static async Task Main(string[] args)
{
    string licenseKey = Environment.GetEnvironmentVariable("LICENSE_KEY");

    if (string.IsNullOrEmpty(licenseKey))
    {
        Console.WriteLine("LICENSE_KEY not found.");
        return;
    }

    if (args.Contains("--console") || Environment.GetEnvironmentVariable("RUN_AS_SERVICE") != "true")
    {
        Console.WriteLine("Running as console.");
        var cancellationTokenSource = new CancellationTokenSource();
        var task = RunAsConsoleAsync(cancellationTokenSource.Token);
        await task;
    }
    else
    {
        Console.WriteLine("Running as Windows service.");
        RunAsWindowsService();
    }
}

Windows服务实现代码

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("Service started successfully.", EventLogEntryType.Information);
                }
                catch (Exception ex)
                {
                    eventLog.WriteEntry($"Error saat menjalankan service: {ex.Message}", EventLogEntryType.Error);
                }
            });

            s.WhenStopped(tc =>
            {
                try
                {
                    tc.Stop();
                    eventLog.WriteEntry("Service stopped successfully.", EventLogEntryType.Information);
                }
                catch (Exception ex)
                {
                    eventLog.WriteEntry($"Error saat menghentikan service: {ex.Message}", EventLogEntryType.Error);
                }
            });
        });

        x.RunAsLocalSystem();
        x.SetDescription("Telegram Bot Service");
        x.SetDisplayName("TelegramBotService");
        x.SetServiceName("TelegramBotService");

        // Pengaturan agar service mulai otomatis dan bisa recovery
        x.StartAutomatically();
        x.EnableServiceRecovery(r => r.RestartService(1)); // Restart setelah 1 menit jika terjadi kesalahan
    });
}
解决方案

核心思路

Windows服务运行在非交互式会话中,可通过Environment.UserInteractive属性判断当前程序是否运行在交互式环境(控制台程序返回true,服务返回false)。结合命令行参数优先级,实现无需环境变量的模式判断:

  1. 如果用户传入--console参数,强制以控制台模式运行
  2. 否则,根据Environment.UserInteractive自动判断:交互式环境跑控制台,非交互式跑服务

修改后的判断逻辑代码

static async Task Main(string[] args)
{
    string licenseKey = Environment.GetEnvironmentVariable("LICENSE_KEY");

    if (string.IsNullOrEmpty(licenseKey))
    {
        Console.WriteLine("未找到LICENSE_KEY。");
        return;
    }

    // 优先处理命令行参数:强制控制台模式
    bool forceConsoleMode = args.Contains("--console");
    // 自动判断运行环境:交互式环境(控制台)为true,服务环境为false
    bool runAsConsole = forceConsoleMode || Environment.UserInteractive;

    if (runAsConsole)
    {
        Console.WriteLine("以控制台模式运行。");
        var cancellationTokenSource = new CancellationTokenSource();
        await RunAsConsoleAsync(cancellationTokenSource.Token);
    }
    else
    {
        Console.WriteLine("以Windows服务模式运行。");
        RunAsWindowsService();
    }
}

原逻辑问题说明

原代码中Environment.GetEnvironmentVariable("RUN_AS_SERVICE") != "true"的判断逻辑存在缺陷:服务安装后该环境变量默认不存在,会直接进入控制台分支。新方案通过系统原生属性自动识别运行环境,无需额外配置环境变量,更适合客户端部署。

内容的提问来源于stack exchange,提问作者RIzky Satria P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 09:43:10