9

我正在使用命令行参数将一些配置传递给 Windows 服务(它将是几个具有不同命令行的实例)。

我的代码如下所示:

HostFactory.Run(x =>                                 
{
    x.Service<MyHost>(s =>
    {                    
        s.ConstructUsing(name => new MyHost());
        s.WhenStarted(tc => tc.Start());             
        s.WhenStopped(tc => tc.Stop());              
    });
    x.AddCommandLineDefinition("sqlserver", v => sqlInstance = v);
}); 

当我安装服务时,我使用:

myhost.exe install -sqlserver:someinstance

不幸的是,sqlserver命令行选项仅在安装阶段可用,并且不转到服务的参数。所以当我运行服务时,我没有得到我需要的参数值。

有没有办法修改TopShelf启动的服务的命令行?

4

3 回答 3

4

我有类似的要求,不幸的是,将命令行参数存储在文件中不是一种选择。

免责声明:此方法仅适用于 Windows

首先我添加了一个安装后操作

x.AfterInstall(
    installSettings =>
    {
         AddCommandLineParametersToStartupOptions(installSettings);
    });

AddCommanLineParameterToStartupOptions我更新服务的ImagePath Windows 注册表项以包含命令行参数。

TopShelf 在此步骤之后添加它的参数,以避免重复,servicenameinstance将它们过滤掉。您可能想要过滤掉的不仅仅是那些,但在我的情况下这已经足够了。

     private static void AddCommandLineParametersToStartupOptions(InstallHostSettings installSettings)
     {
            var serviceKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
                $"SYSTEM\\CurrentControlSet\\Services\\{installSettings.ServiceName}",
                true);

            if (serviceKey == null)
            {
                throw new Exception($"Could not locate Registry Key for service '{installSettings.ServiceName}'");
            }

            var arguments = Environment.GetCommandLineArgs();

            string programName = null;
            StringBuilder argumentsList = new StringBuilder();

            for (int i = 0; i < arguments.Length; i++)
            {
                if (i == 0)
                {
                    // program name is the first argument
                    programName = arguments[i];
                }
                else
                {
                    // Remove these servicename and instance arguments as TopShelf adds them as well
                    // Remove install switch
                    if (arguments[i].StartsWith("-servicename", StringComparison.InvariantCultureIgnoreCase) |
                        arguments[i].StartsWith("-instance", StringComparison.InvariantCultureIgnoreCase) |
                        arguments[i].StartsWith("install", StringComparison.InvariantCultureIgnoreCase))
                    {
                        continue;
                    }
                    argumentsList.Append(" ");
                    argumentsList.Append(arguments[i]);
                }
            }

            // Apply the arguments to the ImagePath value under the service Registry key
            var imageName = $"\"{Environment.CurrentDirectory}\\{programName}\" {argumentsList.ToString()}";
            serviceKey.SetValue("ImagePath", imageName, Microsoft.Win32.RegistryValueKind.String);
}
于 2016-03-16T18:29:11.980 回答
2

在这一点上你不能轻易做到。我会在邮件列表中查看此线程

https://groups.google.com/d/msg/topshelf-discuss/Xu4XR6wGWxw/GFzmKdn_MeYJ

于 2013-03-07T01:06:12.963 回答
2

您不能修改传递给服务的命令行。我通过将这些参数保存到 exe 旁边的配置来解决这个问题。所以用户可以这样做:

service.exe run /sqlserver:connectionstring

并且应用程序将连接字符串保存到文件中(使用 System.IO.File 或使用 ConfigurationManager)

然后,如果用户这样做:

service.exe run

或者,如果该服务作为 Windows 服务运行,那么该应用程序只是从配置加载。

于 2015-02-26T17:17:48.900 回答