在自动启动时将参数传递给 Windows 服务
Pass an argument to a Windows Service at automatic startup
我发现了一些类似的问题,但答案似乎对我的情况没有帮助。我希望将我的服务配置为使用 1 个参数自动启动。
我的服务 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!
}
}
所以我在服务文件名后使用 int 参数 (8081) 注册了我的服务,如下面的屏幕截图所示(如其他类似问题的答案中所建议的)。
当我启动服务时,总是收到错误消息 "The service must be started...."。
如果我在 "Start parameters:" 字段中键入一个整数,服务将正常启动。
如何让 Windows 使用一个参数 (8081) 自动启动我的服务?
编辑:
I did some more tests. Added logging of the args[] parameter. It is
empty. Also I tried to add extra parameters like in this image:
I tried both with and without double-quotes around the arguments, but
they are not passed to the service.
启动服务时,有两个不同的参数列表。
第一个是从命令行获取的,如服务管理工具中的 "path to executable" 所示。如屏幕截图所示,这是您放置参数 8081 的位置。
在 .NET 服务中,这些参数被传递给 Main()
函数。
其次是服务启动参数,在手动启动服务时提供。如果您使用服务管理工具启动服务,则此参数列表取自 "start parameters" 字段,在您的屏幕截图中该字段为空。
在 .NET 服务中,这些参数被传递给 OnStart()
函数。
因此,在您的方案中,您应该修改 Main()
,以便它将命令行参数传递给您的服务 class。通常,您会在构造函数中提供这些,但如果您愿意,也可以使用全局变量。
(有关服务启动的更详细说明,另请参阅 。)
@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);
}
}
然后你只需要在接受参数的服务中添加一个构造函数。
并且现在服务可以通过参数自动启动。
我发现了一些类似的问题,但答案似乎对我的情况没有帮助。我希望将我的服务配置为使用 1 个参数自动启动。
我的服务 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!
}
}
所以我在服务文件名后使用 int 参数 (8081) 注册了我的服务,如下面的屏幕截图所示(如其他类似问题的答案中所建议的)。
当我启动服务时,总是收到错误消息 "The service must be started...."。
如果我在 "Start parameters:" 字段中键入一个整数,服务将正常启动。
如何让 Windows 使用一个参数 (8081) 自动启动我的服务?
编辑:
I did some more tests. Added logging of the args[] parameter. It is empty. Also I tried to add extra parameters like in this image:
I tried both with and without double-quotes around the arguments, but they are not passed to the service.
启动服务时,有两个不同的参数列表。
第一个是从命令行获取的,如服务管理工具中的 "path to executable" 所示。如屏幕截图所示,这是您放置参数 8081 的位置。
在 .NET 服务中,这些参数被传递给 Main()
函数。
其次是服务启动参数,在手动启动服务时提供。如果您使用服务管理工具启动服务,则此参数列表取自 "start parameters" 字段,在您的屏幕截图中该字段为空。
在 .NET 服务中,这些参数被传递给 OnStart()
函数。
因此,在您的方案中,您应该修改 Main()
,以便它将命令行参数传递给您的服务 class。通常,您会在构造函数中提供这些,但如果您愿意,也可以使用全局变量。
(有关服务启动的更详细说明,另请参阅
@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);
}
}
然后你只需要在接受参数的服务中添加一个构造函数。
并且现在服务可以通过参数自动启动。