我现在能够多次实例化我创建的同一个Windows服务。 我设法使用“InstallUtil.exe / servicename = TestX”安装单个实例。 这意味着每个实例都应该在我的Windows服务中列出(请参阅Service instance test1),但仍然停止。
我在许多线程中看到人们使用Timer自动重新启动服务。这真的有必要吗? 是否可以使用“ServiceController”从aclient应用程序重新启动它,我已经尝试但没有成功。
使用后一种方法,我收到一个错误,说我的本地机器上找不到管道终点。 我不确定这实际上与我的问题有关,但是我是否需要为每个新创建的服务实例设置不同的端点?
以下是我为允许多个服务实例化所做的工作:
namespace MyService.Service
{
[RunInstaller(true)]
public partial class MyServiceInstaller : Installer
{
public MyServiceInstaller()
{
InitializeComponent();
}
// Override Install/Uninstall to allow to run various instances of the same Service
// Install via CMD from running from C:\Windows\Microsoft.NET\Framework\v4.0.30319:
// InstallUtil.exe /servicename=test2 Path\bin\Debug\MyService.Service.exe:
public override void Install(System.Collections.IDictionary stateSaver)
{
RetrieveServiceName();
base.Install(stateSaver);
}
// To uninstall:
// InstallUtil.exe -u /servicename=test2 Path\bin\Debug\MyService.Service.exe:
public override void Uninstall(System.Collections.IDictionary savedState)
{
RetrieveServiceName();
base.Uninstall(savedState);
}
// Set up name of each service instance
private void RetrieveServiceName()
{
var serviceName = Context.Parameters["servicename"];
if (!string.IsNullOrEmpty(serviceName))
{
this.serviceInstaller1.ServiceName = serviceName;
this.serviceInstaller1.DisplayName = serviceName;
}
}
}
}
这是来自App.config(我认为这与我的问题无关,但如果我在这里做错了,请告诉我):
<services>
<!-- This section is optional with the new configuration model introduced in .NET framework 4.0 -->
<service name="MyService.Service.MyService" behaviorConfiguration="MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/My.Service/"/>
</baseAddresses>
</host>
<!-- This endpoint is exposed at the base address provided by host -->
<endpoint address="MyServiceAddr" binding="netNamedPipeBinding" contract="MyService.ServiceContract.IMyService"/>
<!-- The mex endpoint is exposed at http://localhost:9000/MyService.Service/service/mex -->
<endpoint address="MyServiceAddr/mex" binding="mexNamedPipeBinding" contract="IMetadataExchange"/>
</service>
</services>
这是我的Proxy Constructor所做的:
private MyServiceProxy(string serviceName)
{
var ctx = new InstanceContext(MyServiceCallbackProxy.Instance);
var binding = new NetNamedPipeBinding();
var channelFactory = new DuplexChannelFactory<IMyServiceService>(ctx, binding,
new EndpointAddress(Constants.ServiceBaseAddress + serviceName));
// Create channel to a specified endpoint
_channel = channelFactory.CreateChannel();
}
最后,我尝试从我的客户端(使用“ServiceController”)按照here启动我的服务。 请注意,找到了服务,但重新启动/使用它是另一回事。这是我的实际客户端代码:
...
static bool serviceExists(string ServiceName)
{
return ServiceController.GetServices().Any(serviceController => serviceController.ServiceName.Equals(ServiceName));
}
static void startService(string ServiceName)
{
ServiceController sc = new ServiceController();
sc.ServiceName = ServiceName;
Console.WriteLine("The {0} service status is currently set to {1}", ServiceName, sc.Status.ToString());
if (sc.Status == ServiceControllerStatus.Stopped)
{
// Start the service if the current status is stopped.
Console.WriteLine("Starting the {0} service ...", ServiceName);
try
{
// Start the service, and wait until its status is "Running".
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running);
// Display the current service status.
Console.WriteLine("The {0} service status is now set to {1}.", ServiceName, sc.Status.ToString());
}
catch (InvalidOperationException e)
{
Console.WriteLine("Could not start the {0} service.", ServiceName);
Console.WriteLine(e.Message);
}
}
else
{
Console.WriteLine("Service {0} already running.", ServiceName);
}
}
static void Main(string[] args)
{
if (serviceExists("test1"))
{
Console.WriteLine("Service exists");
}
else
{
Console.WriteLine("Service doesn't exists");
}
startService("test1");
// Connect to Proxy in order to run multiple APIs in parallel
MyServiceProxy ServiceInst = MyServiceProxy.Instance("test1");
…
服务主机以这种方式启动:
public MyServiceWindowsService(sting serviceName)
{
InitializeComponent();
// Name the service
ServiceName = serviceName;
}
protected override void OnStart(string[] args)
{
StartServiceHost();
}
private void StartServiceHost()
{
// Stop the service before starting the service
StopServiceHost();
ServiceHost = new ServiceHost(typeof(MyService));
// Open the ServiceHostBase to create listeners and start listening for messages
ServiceHost.Open();
}
主要是做:
public static void Main(string[] argsIn)
{
ServiceBase[] servicesToRun = new ServiceBase[]
{
new MyServiceWindowsService(argsIn[0]),
};
...
在您的客户端中,EndPoint
的地址是从Windows服务的名称动态构造的:
new EndpointAddress(Constants.ServiceBaseAddress + serviceName)
您还需要让ServiceHost
在StartServiceHost()
中使用此地址:
Uri uri = new Uri(Constants.ServiceBaseAddress + ServiceName);
ServiceHost = new ServiceHost(typeof(MyService), uri);
ServiceHost.Open();