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

时间:2011-05-18 11:04:40

标签: c# windows-services

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

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

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

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:2)

自从我遇到这个问题以来,我加了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;
    }
}

答案 2 :(得分:0)

与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 + ") ");
                }
            }
        }

    }

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

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

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

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

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