Моя служба WCF, установленная как часть служб Windows, останавливается. Как запустить ее с моего клиента без использования таймера? - PullRequest
0 голосов
/ 09 апреля 2019

Теперь я могу несколько раз создавать экземпляр одной и той же службы Windows, которую я создал.
Мне удается установить отдельные экземпляры с помощью «InstallUtil.exe /servicename=TestX".
». Это означает, что каждый экземпляр отображается в списке вмои службы Windows, как и должно (см. экземпляр службы test1 ), но остаются остановленными.

Я видел во многих потоках, что люди используют таймер для автоматического перезапуска службы.Это действительно необходимо?
Можно ли просто перезапустить его из приложения-клиента с помощью «ServiceController», который я пробовал, но безуспешно.

Используя последний подход, я получаю сообщение об ошибке, в котором говорится, что на моем локальном компьютере невозможно найти точку конца трубы.
Я не уверен, что это на самом деле связано с моей проблемой, но нужно лиустановить разные конечные точки для каждого нового экземпляра моего сервиса?

Вот что я сделал, чтобы разрешить несколько экземпляров службы:

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>

Вот что делает мой прокси-конструктор:

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») согласно здесь .
Обратите внимание, что служба найдена, но перезапуск / использование ее - это другое дело.Вот мой действительный код клиента:

...
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]),
  };
...

1 Ответ

0 голосов
/ 10 апреля 2019

В вашем клиенте адрес EndPoint создается динамически из имени службы Windows:

new EndpointAddress(Constants.ServiceBaseAddress + serviceName)

Вам также нужно, чтобы ServiceHost использовал этот адрес в StartServiceHost():

Uri uri = new Uri(Constants.ServiceBaseAddress + ServiceName);
ServiceHost = new ServiceHost(typeof(MyService), uri);

ServiceHost.Open();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...