Windows服务 – 如何使名称可配置

我在C#中编写了一个Windows服务。 一开始的要求是我应该只运行该服务的一个实例,但是已经改变了,现在我需要多个实例。 这就是我需要根据配置文件更改服务名称的原因。

使用正确的名称注册的最佳方法是什么? 我应该写另一个工具来做吗? 我可以从App.config文件中读取名称并在服务和安装程序类中相应地设置它吗?

PS>我真的不明白名称的工作原理 – 应该在服务和安装程序类中设置名称,但是在使用installutil.exe甚至PowerShell new-service进行安装时,也应该指定名称。 那必须是一样的吗? 或者一个覆盖另一个?

您只需从app.config中读取它并在安装程序类中进行设置即可。
通常,会自动创建一个inheritance自Installer的类。 它包含System.ServiceProcess.ServiceInstaller类型的成员,很可能名为serviceProcessInstaller1 。 这有一个您可以设置的属性ServiceName 。 此外,您需要将ServiceBase派生类的ServiceName属性设置为相同的值。
在默认实现中,这些在相应的InitializeComponent方法中设置为常量值,但没有理由坚持这一点。 它可以动态完成而不会出现问题。

我虽然因为遇到这个问题而增加了2美分。 我有一个名为“ProjectInstaller.cs”的文件,其下有设计者和资源。 在设计中打开它会将MyServiceInstaller和MyProjectInstaller显示为设计图面上的项目。 我能够更改ProjectInstaller()构造函数中的名称,并从模块目录手动加载配置文件:

 public ProjectInstaller() { InitializeComponent(); var config = ConfigurationManager.OpenExeConfiguration(this.GetType().Assembly.Location); if (config.AppSettings.Settings["ServiceName"] != null) { this.MyServiceInstaller.ServiceName = config.AppSettings.Settings["ServiceName"].Value; } if (config.AppSettings.Settings["DisplayName"] != null) { this.MyServiceInstaller.DisplayName = config.AppSettings.Settings["DisplayName"].Value; } } 

与Jason Goemaat的答案一样,这就是你如何遍历项目中所有可用的安装程序,这样可以节省您确保将每个新服务添加到此类的时间。 在我的项目中,我总共有12个服务(我们在这里和那里添加一个新服务),我们希望它们按实例名称组合在一起,因此SVC(实例1)服务XX和SVC(实例1)服务YY在服务管理单元控制台中查看时,它们彼此相邻。

  public ProjectInstaller() { InitializeComponent(); var config = ConfigurationManager.OpenExeConfiguration(this.GetType().Assembly.Location); string instanceName = config.AppSettings.Settings["Installer_NamedInstanceName"].Value; string instanceID = config.AppSettings.Settings["Installer_NamedInstanceID"].Value; bool usesNamedInstance = !string.IsNullOrWhiteSpace(instanceName) && !string.IsNullOrWhiteSpace(instanceID); if (usesNamedInstance) { foreach (var installer in this.Installers) { if (installer is ServiceInstaller) { var ins = (ServiceInstaller)installer; ins.ServiceName = ins.ServiceName + "-" + instanceID; // Want the service to be named SVC (Instance Name) Audit Log Blah Blah Service ins.DisplayName = ins.DisplayName.Replace("SVC ", "SVC (" + instanceName + ") "); } } } } 

但是 ,您还需要做其他事情 – 初始化服务时,您还必须更改服务名称,否则您将收到“可执行文件未实现服务”的错误。 我通过在Program.cs实现以下代码来完成此操作:

  internal static void HandleCustomServiceName(ServiceBase sbase) { if (!string.IsNullOrWhiteSpace(customInstanceName)) { sbase.ServiceName = sbase.ServiceName + "-" + customInstanceName; } } 

然后,在每个服务的构造函数中:

  public SystemEventWatcher() { InitializeComponent(); Program.HandleCustomServiceName(this); } 

我赞成Jason的答案,为在我自己的项目中实现这一点铺平了道路。 谢谢!