在自动启动时向Windows服务传递参数

4
我发现一些类似的问题,但答案似乎不能帮助我。我希望配置我的服务以自动启动并带有一个参数。
我的服务OnStart方法如下:
    /// <summary>
    /// Starts the service
    /// </summary>
    /// <param name="args">args must contain the listening port number of the service</param>
    protected override void OnStart(string[] args)
    {
        if (args != null && args.Length > 0)
        {
            int port = -1;
            if (int.TryParse(args[0], out port) && port >= 0 && port <= 65535)
            {
                server.Start(port);
            }
            else
            {
                Log.Entry("Port value " + args[0] + " is not a valid port number!", Log.Level.Error);
            }
        }
        else
        {
            Log.Entry("Service must be started with the port number (integer) as parameter.", Log.Level.Error);
            throw new ArgumentNullException("Service must be started with the port number (integer) as parameter."); // stop the service!
        }
    }

所以,我按照下面截图中的建议(与其他类似问题的答案相同),在服务文件名后注册了带有整数参数(8081)的服务。

enter image description here

当我启动服务时,总是会收到错误消息“必须启动该服务...”。
如果我在“启动参数:”字段中键入一个整数,则服务会正常启动。
如何让Windows自动使用一个参数(8081)启动我的服务?
编辑:
我进行了更多的测试。添加了args[]参数的日志记录。它是空的。我还尝试添加额外的参数,就像这张图片中一样:
我尝试用和不用双引号包围参数,但它们没有传递给服务。

1
@Filburt 如果你把它放在那里,只有当你从对话框手动“启动”或“重新启动”服务时才会使用它,而不是在系统启动时自动启动服务。 - Matthew Watson
有什么特别的原因必须通过参数传递,而不是在.NET配置文件中进行正常的输入呢? - Damien_The_Unbeliever
@Damien_The_Unbeliever 主要是为了简单起见。如果以这种方式不可能,我会回归到配置文件。这让我有些困扰,因为应该有可能这样做,这让我很好奇想知道如何实现。 - Mr. Blonde
四年后,我发现在启动参数中提供的参数实际上被传递到了服务的OnStart方法中。这是有变化吗? - Peter
2个回答

19

当一个服务被启动时,有两个不同的参数列表。

第一个参数列表来自命令行,如Services管理工具中的“可执行文件路径”所示。这是您在屏幕截图中添加了8081参数的位置。

在.NET服务中,这些参数将传递给Main()函数。

第二个参数列表是服务启动参数,在手动启动服务时提供。如果使用Services管理工具启动服务,则该参数列表取自“启动参数”字段,在您的屏幕截图中为空。

在.NET服务中,这些参数将传递给OnStart()函数。

因此,在您的情况下,您应修改Main()函数以将命令行参数传递给您的服务类。通常,您会在构造函数中提供这些参数,但如果您更喜欢,也可以使用全局变量。

(有关服务启动的更详细说明,请参见此答案。)


3

@Harry Johnston 的回答是正确的。我只想补充一点代码来支持它。

服务的入口点位于“Program.cs”文件中。默认情况下,它看起来像这样:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
        {
            new Service()
        };
        ServiceBase.Run(ServicesToRun);
    }
}

服务没有传递参数。添加args参数允许服务接收参数。

static class Program
{
    static void Main(string[] args)
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[]
        {
            new Service(args[0])
        };
        ServiceBase.Run(ServicesToRun);
    }
}

接下来,您只需向服务添加一个接受参数的构造函数。

现在该服务可以自动启动并接收参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接