在服务器上安装相同Windows服务的多个实例

Swi*_*ers 92 windows windows-installer windows-services installutil

所以我们已经制作了一个Windows服务来将数据提供给我们的客户端应用程序,一切都很顺利.客户端提出了一个有趣的配置请求,该请求要求在同一服务器上运行此服务的两个实例,并将其配置为指向不同的数据库.

到目前为止,我还没有能够实现这一点,并希望我的同事stackoverflow成员可以提供一些提示,为什么.

目前的设置:

我已经设置了包含windows服务的项目,从现在开始我们称之为AppService,以及处理自定义安装步骤的ProjectInstaller.cs文件,根据App.config中的键设置服务名称,如此:

this.serviceInstaller1.ServiceName = Util.ServiceName;
this.serviceInstaller1.DisplayName = Util.ServiceName;
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Util只是一个静态类,可以从配置文件中加载服务名称.

从这里开始,我尝试了两种不同的方法来安装这两种服务,并且都以相同的方式失败.

第一种方法是简单地安装服务的第一个副本,复制已安装的目录并重命名,然后在修改应用程序配置后运行以下命令以更改所需的服务名称:

InstallUtil.exe /i AppService.exe
Run Code Online (Sandbox Code Playgroud)

当这不起作用时,我尝试创建第二个安装程序项目,编辑配置文件并构建第二个安装程序.当我运行安装程序时它工作正常,但服务没有显示在services.msc中,所以我针对第二个安装的代码库运行了上一个命令.

两次我都收到了InstallUtil的以下输出(仅限相关部分):

运行事务安装.

开始安装的安装阶段.

安装服务App Service Two ... Service App Service 2已成功安装.在日志应用程序中创建EventLog源App Service二...

安装阶段发生异常.System.NullReferenceException:未将对象引用设置为对象的实例.

安装的回滚阶段正在开始.

将事件日志还原到源App Service 2的先前状态.服务应用程序服务2正在从系统中删除...服务应用程序服务2已成功从系统中删除.

回滚阶段成功完成.

事务处理安装已完成.安装失败,并且已执行回滚.

对于冗长的帖子感到抱歉,想确保有足够的相关信息.到目前为止已经难倒我的部分是,它指出该服务的安装成功完成和它关系到创建的NullReferenceException异常似乎得到抛出的事件日志源之后.因此,如果有人知道我做错了什么或有更好的方法,那将非常感激.

jam*_*vey 81

你试过sc/service controller util吗?类型

sc create
Run Code Online (Sandbox Code Playgroud)

在命令行,它将为您提供帮助条目.我想我过去为Subversion做过这个,并将本文作为参考:

http://svn.apache.org/repos/asf/subversion/trunk/notes/windows-service.txt

  • wordpress博客的链接已更改为:http://journalofasoftwaredev.wordpress.com/2008/07/ (9认同)
  • 我发现这个页面很有用:`http:// journalofasoftwaredev.wordpress.com/2008/07/16/multiple-instances-of-same-windows-service /`.您可以在安装程序中插入代码以获取运行installutil时所需的服务名称. (5认同)

Mar*_*man 19

您可以通过执行以下操作来运行同一服务的多个版本:

1)将Service可执行文件和config复制到其自己的文件夹中.

2)将Install.Exe复制到服务可执行文件夹(来自.net framework文件夹)

3)在服务可执行文件夹中创建一个名为Install.exe.config的配置文件,其中包含以下内容(唯一服务名称):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="ServiceName" value="The Service Name"/>
    <add key="DisplayName" value="The Service Display Name"/>
  </appSettings>
</configuration>
Run Code Online (Sandbox Code Playgroud)

4)创建批处理文件以安装具有以下内容的服务:

REM Install
InstallUtil.exe YourService.exe
pause
Run Code Online (Sandbox Code Playgroud)

5)在那里,创建一个卸载批处理文件

REM Uninstall
InstallUtil.exe -u YourService.exe
pause
Run Code Online (Sandbox Code Playgroud)

编辑:

请注意,如果我错过了什么,这里是ServiceInstaller类(根据需要调整):

using System.Configuration;

namespace Made4Print
{
    partial class ServiceInstaller
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        private System.ServiceProcess.ServiceInstaller FileProcessingServiceInstaller;
        private System.ServiceProcess.ServiceProcessInstaller FileProcessingServiceProcessInstaller;

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.FileProcessingServiceInstaller = new System.ServiceProcess.ServiceInstaller();
            this.FileProcessingServiceProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
            // 
            // FileProcessingServiceInstaller
            // 
            this.FileProcessingServiceInstaller.ServiceName = ServiceName;
            this.FileProcessingServiceInstaller.DisplayName = DisplayName;
            // 
            // FileProcessingServiceProcessInstaller
            // 
            this.FileProcessingServiceProcessInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
            this.FileProcessingServiceProcessInstaller.Password = null;
            this.FileProcessingServiceProcessInstaller.Username = null;
            // 
            // ServiceInstaller
            // 
            this.Installers.AddRange(new System.Configuration.Install.Installer[] { this.FileProcessingServiceInstaller, this.FileProcessingServiceProcessInstaller });
        }

        #endregion

        private string ServiceName
        {
            get
            {
                return (ConfigurationManager.AppSettings["ServiceName"] == null ? "Made4PrintFileProcessingService" : ConfigurationManager.AppSettings["ServiceName"].ToString());
            }
        }

        private string DisplayName
        {
            get
            {
                return (ConfigurationManager.AppSettings["DisplayName"] == null ? "Made4Print File Processing Service" : ConfigurationManager.AppSettings["DisplayName"].ToString());
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 巨大的帮助谢谢.我认为安装配置文件需要命名为InstallUtil.exe.confg而不是InstallUtil.exe的Install.exe.config (2认同)

小智 18

  sc create [servicename] binpath= [path to your exe]
Run Code Online (Sandbox Code Playgroud)

这个解决方案对我有用.

  • 只是指出; `[你的exe的路径]`必须是完整的路径,不要忘记`binpath =`之后的空格 (3认同)
  • 这确实允许多次安装服务.但是,服务安装程序提供的所有信息.Fe描述,登录类型等被忽略 (2认同)

Jon*_*ney 10

老问题,我知道,但我很幸运使用InstallUtil.exe上的/ servicename选项.我没有看到它在内置帮助中列出.

InstallUtil.exe /servicename="My Service" MyService.exe
Run Code Online (Sandbox Code Playgroud)

我不完全确定我在哪里读到这个,但我从那以后就没见过.因人而异.

  • 返回此错误:`安装阶段发生异常.System.ComponentModel.Win32Exception:指定的服务已经存在 (3认同)

And*_*rea 8

另一种快捷方式指定自定义值ServiceName,并DisplayName使用installutil命令行参数.

  1. 在您的ProjectInstaller类中覆盖虚拟方法Install(IDictionary stateSaver)Uninstall(IDictionary savedState)

    public override void Install(System.Collections.IDictionary stateSaver)
    {
        GetCustomServiceName();
        base.Install(stateSaver);
    }
    
    public override void Uninstall(System.Collections.IDictionary savedState)
    {
        GetCustomServiceName();
        base.Uninstall(savedState);
    }
    
    //Retrieve custom service name from installutil command line parameters
    private void GetCustomServiceName()
    {
        string customServiceName = Context.Parameters["servicename"];
        if (!string.IsNullOrEmpty(customServiceName))
        {
            serviceInstaller1.ServiceName = customServiceName;
            serviceInstaller1.DisplayName = customServiceName;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 建立你的项目
  3. installutil使用/servicename参数添加自定义名称来安装服务:

    installutil.exe /servicename="CustomServiceName" "c:\pathToService\SrvcExecutable.exe"
    
    Run Code Online (Sandbox Code Playgroud)

请注意,如果未/servicename在命令行中指定,将安装ServiceInstaller属性/ config中指定的ServiceName和DisplayName值的服务.

  • 杰出的!!谢谢 - 这正是所需要的,而且恰到好处。 (2认同)

tri*_*fee 6

在使用我们的自动部署软件频繁安装/卸载并排Windows服务时,我没有太多运气,但我最终想出了以下内容,它允许我传入一个参数来指定后缀到命令行上的服务名称.它还允许设计师正常运行,并且可以根据需要轻松调整以覆盖整个名称.

public partial class ProjectInstaller : System.Configuration.Install.Installer
{
  protected override void OnBeforeInstall(IDictionary savedState)
  {
    base.OnBeforeInstall(savedState);
    SetNames();
  }

  protected override void OnBeforeUninstall(IDictionary savedState)
  {
    base.OnBeforeUninstall(savedState);
    SetNames();
  }

  private void SetNames()
  {
    this.serviceInstaller1.DisplayName = AddSuffix(this.serviceInstaller1.DisplayName);
    this.serviceInstaller1.ServiceName = AddSuffix(this.serviceInstaller1.ServiceName);
  }

  private string AddSuffix(string originalName)
  {
    if (!String.IsNullOrWhiteSpace(this.Context.Parameters["ServiceSuffix"]))
      return originalName + " - " + this.Context.Parameters["ServiceSuffix"];
    else
      return originalName;
  }
}
Run Code Online (Sandbox Code Playgroud)

考虑到这一点,我可以执行以下操作:如果我已将服务称为"Awesome Service",那么我可以按如下方式安装服务的UAT版本:

InstallUtil.exe /ServiceSuffix="UAT" MyService.exe

这将创建名为"Awesome Service - UAT"的服务.我们使用它来运行在一台机器上并行运行的相同服务的DEVINT,TESTING和ACCEPTANCE版本.每个版本都有自己的一组文件/配置 - 我没有尝试过这个来安装指向同一组文件的多个服务.

注意:您必须使用相同的/ServiceSuffix参数来卸载服务,因此您要执行以下操作来卸载:

InstallUtil.exe /u /ServiceSuffix="UAT" MyService.exe