安装的多个实例,同windows服务的服务器上
-
16-09-2019 - |
题
因此,我们已经产生的windows服务饲料的数据对我们的客户应用程序,一切都会很大。客户已经想出了一个有趣的配置请求,要求两个实例的这种服务在同一服务器上运行的,并配置点在单独的数据库。
到目前为止,我还没有能够得到这样的事情发生,并希望我的同胞计算器成员可能可以得到一些提示为什么。
当前设置:
我已经设置了该项目包含windows服务,我们就叫它AppService从现在起,ProjectInstaller.cs文件,处理定义安装的步骤来设置的服务名称的基础上的一个关键的应用程序。config像这样:
this.serviceInstaller1.ServiceName = Util.ServiceName;
this.serviceInstaller1.DisplayName = Util.ServiceName;
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
在这种情况下工具只是一个静态的类tha tloads服务名称从配置文件。
从这里向前我曾试图用两种不同的方式,获得这两种服务,安装和两个已经失败,在一个相同的方式。
第一种方式是简单地安装的第一份服务,复制的安装目录和它改名,然后跑的如下命令修改后应用程序配置改变所需的服务名称:
InstallUtil.exe /i AppService.exe
当没有工作我试图建立第二个安装项目、编辑配置文件和建造第二次安装。当我跑到安装,它工作得很好,但服务并没有显示在服务。msc所以我跑了先前的命令的反对的第二个安装码的基础。
两次我收到了以下的产出从InstallUtil(有关部分):
运行交易的安装。
开始安装阶段的安装。
安装服务应用程序服务的两个...业务应用程序服务的两个已经成功地安装。创造的事件日志源应用程序服务两个在日志应用程序...
一个例外发生在安装阶段。系统。NullReferenceException:目的参考,不设置为一个象的实例。
回滚阶段安装开始。
恢复活动记录到以前的状态为源应用程序服务的两个。业务应用程序服务的两个正从系统中除去...业务应用程序服务的两个成功从系统中删除。
回退的阶段已成功完成。
该事务处理的安装已经完成。安装的失败,并回滚已经执行。
对不起长篇大论后,希望确保有足够的相关信息。一块,到目前为止我已经困难的是,它的国家安装的服务的成功完成和其后,才去创造的事件日志源,NullReferenceException似乎得到抛出。所以如果有人知道我在做什么错误的或者具有更好的方法,它将不胜感激。
解决方案
你有没有尝试过的sc/服务器控制工具?类型
sc create
在命令行,它将给你的帮助的条目。我想我已经做到了这一点在过去的为颠复和使用 这篇文章 作为一个参考:
http://svn.apache.org/repos/asf/subversion/trunk/notes/windows-service.txt
其他提示
你可以运行多个版本相同的服务做如下:
1)复制服务的可执行和配置到其自己的文件夹。
2)复制Install.Exe 该服务可执行的文件夹(。净框架文件夹)
3)创建一个配置文件称为安装。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>
4)创建一批文件的安装服务有以下内容:
REM Install
InstallUtil.exe YourService.exe
pause
5)虽然你在那里,创建一个卸载批文件
REM Uninstall
InstallUtil.exe -u YourService.exe
pause
编辑:
注意到肯定的如果我错过了什么,这里是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());
}
}
}
}
sc create [servicename] binpath= [path to your exe]
这个方案为我工作。
老问题,我知道,但我已经运用的/服务名称的选择上InstallUtil.exe.我看不到它列在内的帮助。
InstallUtil.exe /servicename="My Service" MyService.exe
我不能完全肯定在那里我第一次读到关于这一点,但我还没有看到它。情况因人而异。
另一个快速的方式来指定一个定义的价值 ServiceName
和 DisplayName
是的使用 installutil
命令行参数。
在你
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; } }
- 建立你的项目
安装的服务
installutil
加入你的自定名称的使用/servicename
参数:installutil.exe /servicename="CustomServiceName" "c:\pathToService\SrvcExecutable.exe"
请注意,如果不指定 /servicename
在命令行的服务将被安装与服务名称和显示名称值中指定ProjectInstaller性质/配置
我没有运用上述方法时使用我们的自动部署的软件要经常安装/卸载边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;
}
}
铭记这一点,我可以做到以下几点:如果我打电话服务"服务"然后我可以安装一个UAT版本的服务如下:
InstallUtil.exe /ServiceSuffix="UAT" MyService.exe
这将创建服务的名称"服务-UAT".我们已经用这个运行DEVINT、测试和接受的版本相同的服务的运行边上的一个单一的机。每个版本都有其自己的一套文件/配置-我没有尝试过这个安装多种服务指在同一文件集。
注:你必须使用相同的 /ServiceSuffix
参卸载业务,所以,你愿意执行以下卸载:
InstallUtil.exe /u /ServiceSuffix="UAT" MyService.exe
我做了什么,使这项工作是储存服务的姓名和名称显示中的应用程序。config为我服务。然后在我的安装类,我加载的程序。配置作如下和使用xpath,获得价值并将其应用到ServiceInstaller.服务名称和ServiceInstaller.显示名称之前,呼吁InitializeComponent().这个假设你不是已经设定这些性质在InitializeComponent(),在这种情况下,设置自己的配置文件将会被忽略。以下代码是什么我打电话给我安装类的构造之前,InitializeComponent():
private void SetServiceName()
{
string configurationFilePath = Path.ChangeExtension(Assembly.GetExecutingAssembly().Location, "exe.config");
XmlDocument doc = new XmlDocument();
doc.Load(configurationFilePath);
XmlNode serviceName = doc.SelectSingleNode("/xpath/to/your/@serviceName");
XmlNode displayName = doc.SelectSingleNode("/xpath/to/your/@displayName");
if (serviceName != null && !string.IsNullOrEmpty(serviceName.Value))
{
this.serviceInstaller.ServiceName = serviceName.Value;
}
if (displayName != null && !string.IsNullOrEmpty(displayName.Value))
{
this.serviceInstaller.DisplayName = displayName.Value;
}
}
我不相信读的配置文件直接从ConfigurationManager.若或类似的东西会工作时安装运行,它的运行方面的InstallUtil.exe不是你服务的.exe。你可以做一些与ConfigurationManager.OpenExeConfiguration,然而在我的情况下,这没工作,因为我是试图获得在定义构成部分,这不是装载。
只是为了改善完美的答案@克里斯。房子。00 此, 你可以考虑下列功能读取你的应用程序设置:
public void GetServiceAndDisplayName(out string serviceNameVar, out string displayNameVar)
{
string configurationFilePath = Path.ChangeExtension(Assembly.GetExecutingAssembly().Location, "exe.config");
XmlDocument doc = new XmlDocument();
doc.Load(configurationFilePath);
XmlNode serviceName = doc.SelectSingleNode("//appSettings//add[@key='ServiceName']");
XmlNode displayName = doc.SelectSingleNode("//appSettings//add[@key='DisplayName']");
if (serviceName != null && (serviceName.Attributes != null && (serviceName.Attributes["value"] != null)))
{
serviceNameVar = serviceName.Attributes["value"].Value;
}
else
{
serviceNameVar = "Custom.Service.Name";
}
if (displayName != null && (displayName.Attributes != null && (displayName.Attributes["value"] != null)))
{
displayNameVar = displayName.Attributes["value"].Value;
}
else
{
displayNameVar = "Custom.Service.DisplayName";
}
}
最简单的方法是基于该服务名称的dll名称:
string sAssPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
string sAssName = System.IO.Path.GetFileNameWithoutExtension(sAssPath);
if ((this.ServiceInstaller1.ServiceName != sAssName)) {
this.ServiceInstaller1.ServiceName = sAssName;
this.ServiceInstaller1.DisplayName = sAssName;
}