Problem
I had written an application using Spring.Net for dependency injection - and some of the other features it provides - and Topshelf. The application could then be written as a console application and then installed and run as a Windows service using Topshelf’s handy ‘install’ command line parameter.
I was using XML files to configure Spring.Net. This turned out to be significant.
The application worked sweet as a nut as a console application and installed successfully as a Windows service. However, when I tried to run the Windows service using net start all I got was “The service is not responding to the control function”.
Solution
In the app.config file I had a spring configuration section that referenced external files for the spring.context:
<spring> <context> <resource uri="file://Config/SpringContext.xml" /> <resource uri="file://Config/SpringDataAccess.xml" /> <resource uri="file://Config/SpringVelocity.xml" /> </context> <parsers> <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" /> <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" /> </parsers> </spring>
The XML configuration files were set to “Copy always” and had been copied into the application directory correctly.
Poking around in the Event Viewer I spotted an interesting error log message. Essentially it said “Exception: Error creating context 'spring.root': Could not find file 'C:\Windows\system32\Config\SpringContext.xml'.”
That was weird because the path (C:\Windows\system32) is not where I had put the application but clearly it was where the Windows service was being run from.
A quick solution was to reconfigure the application to use embedded resources for the configuration files:
<spring> <context> <resource uri="assembly://Assembly.Name.Here/Namespace.Here/Config.SpringContext.xml" /> <resource uri="assembly://Assembly.Name.Here/Namespace.Here/Config.SpringDataAccess.xml" /> <resource uri="assembly://Assembly.Name.Here/Namespace.Here/Config.SpringVelocity.xml" /> </context> <parsers> <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" /> <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" /> <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" /> </parsers> </spring>
The service now started correctly.