Проблема с хостингом службы WCF в службе Windows

У меня есть служба WCF, размещенная внутри службы Windows. Служба Windows имеет метод OnStart, подобный этому:

protected override void OnStart(string[] args)
{
  serviceHost = new ServiceHost(typeof (RouterService));
  serviceHost.Open();
}

Теперь это довольно минимально, так как я пытаюсь найти проблему. Поскольку я не обрабатывал здесь какие-либо ошибки, все исключения на этом этапе должны были прекратить запуск службы должным образом. Он начнется, а затем автоматически остановится снова.

Мой конфигурационный файл для службы WCF выглядит так:

<?xml version="1.0"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
  </startup>
  <system.serviceModel>
    <services>
      <service name="WcfService.RouterService"
               behaviorConfiguration="serviceBehavior" >
        <endpoint address="RouterService" contract="WcfService.IRouterService" binding="wsHttpBinding" bindingConfiguration="NoSecurity" />
        <endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding" />
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000"/>
          </baseAddresses>
        </host>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="NoSecurity">
          <security mode="None" />
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="serviceBehavior" >
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Кроме того, я добавил пользователя NETWORK SERVICE (который работает, чтобы иметь возможность прослушивать Http на указанном порту:

netsh http add urlacl url=http://+:8000/ user="NETWORK SERVICE"

Теперь, в клиенте, я выбираю Add Service Reference. Я могу найти сервер, и VS также удается создать конфигурацию и сделать прокси файлы. Затем внутри клиента я делаю экземпляр прокси и открываю его. Все все в порядке. Но при вызове первого метода в прокси я получаю следующее исключение:

Служба HTTP, расположенная в http://localhost:8000/RouterService, слишком занята.

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

ИЗМЕНИТЬ

Хорошо, теперь я узнал, что мой TestServer (а не клиент Windows, а консольное приложение) также дает ту же ошибку. Ранее сегодня этого не произошло, и ни служба WCF, ни TestServer не были изменены.

Затем я попытался изменить порт на 8080 вместо 8000, и он сработал. Затем я попробовал то же самое для службы Windows, и это также сработало (после запуска команды netsh http на новом порту)

Так что-то случилось с http на порту 8000 по какой-то причине. Конечно, я попытался перезапустить систему.

Это меня озадачивает, поэтому, если кто-нибудь знает, что здесь происходит, я был бы признателен.

Ответы

Ответ 1

Хорошо, после долгого времени, пытаясь выяснить, что здесь произошло, я нашел решение.

После того, как я создал службу Windows и попытался запустить ее, я не смог, потому что мне пришлось регистрировать пользователя NETWORK SERVICE для прослушивания на http post 8000. Поэтому я выполнил эту команду:

netsh http add urlacl url = http://+: 8000/ RouterService user = "NETWORK SERVICE"

Он дал успешный результат, но затем я попытался запустить службу и получил то же сообщение об ошибке. Затем я выполнил ту же команду без указания RouterService:

netsh http add urlacl url = http://+: 8000/user = "NETWORK SERVICE"

Это дало успешный результат, и теперь моя служба Windows запущена без каких-либо проблем, но у меня возникли проблемы, упомянутые выше.

Кажется, что первый вызов netsh вызывает все эти проблемы. Я попытался удалить его с помощью следующей команды:

netsh http delete urlacl url = http://+: 8000/ RouterService

И тогда все сработало отлично.

Сука отлаживает это, поскольку исключение не имеет ничего общего с реальной проблемой, поэтому я надеюсь, что этот вопрос может спасти кого-то еще пару часов:)

Ответ 2

После ответа @oyvind-knobloch-brathen подумайте о том, чтобы использовать известные строки SID вместо "командной строки" пользователя, это даст вам перекрестную культурную переносимость (у меня возникли проблемы с французской локализованной машиной Win7). Для получения дополнительной информации см. строки SID. Для вашего случая это будет:

netsh http add urlacl url = http://+: 8000/sddl = "O: NS"

ссылка на SDDL на MSDN.