Thursday, July 16, 2009

Host WCF service in Windows service

Hosting WCF service in windows service may cause "Access is denied" error:


Service cannot be started. System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:8888/docstore/. Your process does not have access rights to this namespace (see http://go.microsoft.com/fwlink/?LinkId=70353 for details). ---> System.Net.HttpListenerException: Access is denied
at System.Net.HttpListener.AddAll()
at System.Net.HttpListener.Start()
at System.ServiceModel.Channels.SharedHttpTransportManager.OnOpen()
--- End of inner exception stack trace ---
at System.ServiceModel.Channels.SharedHttpTransportManager.OnOpen()
at System.ServiceModel.Channels.TransportManager.Open(TransportChannelListener channelListener)
at System.ServiceModel.Channels.TransportManagerContainer.Open(SelectTransportManagersCallback selectTransportManagerCallback)
at System.ServiceModel.Channels.TransportChannelListener.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.HttpChannelListener.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan t...

For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.


MSDN briefs the light on how to configure such service.

For short, on Windows 2003 you have to execute the following command:

httpcfg set urlacl /u {http://URL:Port/ | https://URL:Port/} /aACL


I had several problems with this command:


  1. No httpcfg installed. It shipped with Win2003 server, but may not be installed by default. This link explains how you can obtain it if you're Win2003/XP user.

  2. Value for the /u argument. In my case I just copied the URL I got in stack trace above: http://+:8888/docstore/.

  3. Value for the /a argument. It takes a string that contains an Access Control List (ACL) in the form of a Security Descriptor Definition Language (SDDL) string.



If you look at SDDL string for first time you can harm your brain, here is an example from MSDN:


"O:DAG:DAD:(A;;RPWPCCDCLCRCWOWDSDSW;;;SY)
(A;;RPWPCCDCLCRCWOWDSDSW;;;DA)
(OA;;CCDC;bf967aba-0de6-11d0-a285-00aa003049e2;;AO)
(OA;;CCDC;bf967a9c-0de6-11d0-a285-00aa003049e2;;AO)
(OA;;CCDC;6da8a4ff-0e52-11d0-a286-00aa003049e2;;AO)
(OA;;CCDC;bf967aa8-0de6-11d0-a285-00aa003049e2;;PO)
(A;;RPLCRC;;;AU)S:(AU;SAFA;WDWOSDWPCCDCSW;;;WD)"


I've found a tool by Dominick Baier (HttpCfg ACL Helper) that can help you to build an ACL string. You can found its description and link to sources on Dominick's blog.

If you don't have VS at hand you can download HttpCfg ACL Helper binary here (3 KB).

When you run it it will prompt to add user account under which you will run the windows service and in the output it will build the command for you (thank you Dominick!):