Проблема с хостингом службы 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.