192 lines
9.2 KiB
XML
192 lines
9.2 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!--
|
|
/*
|
|
* Copyright 2002-2010 the original author or authors.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
-->
|
|
<chapter xml:id="windows-service" xmlns="http://docbook.org/ns/docbook" version="5">
|
|
<title>Windows Services</title>
|
|
|
|
<sect1>
|
|
<title>Remarks</title>
|
|
<para>
|
|
This is functionality that will be included after the
|
|
1.0 release. If you want to use these features please get the
|
|
code from CVS <ulink url="http://opensource.atlassian.com/confluence/spring/display/NET/Project+Structure"></ulink>
|
|
(instructions) or from the download section of the Spring.NET website that contains an
|
|
.zip with the full CVS tree.
|
|
In addition to this documentation
|
|
you can refer to the example program located at
|
|
<literal>examples\Spring\Spring.Examples.WindowsService</literal>
|
|
to better understand the package. Please check the Spring.NET
|
|
<ulink url="http://www.springframework.net/doc/reference/windows-service.html">website</ulink>
|
|
for the latest updates to this document.
|
|
</para>
|
|
</sect1>
|
|
<sect1>
|
|
<title>Introduction</title>
|
|
<para>
|
|
Developers usually create Windows Services using the
|
|
Visual Studio .NET wizard. While not difficult to do, this
|
|
procedure is repetative and does not encourage separation between
|
|
infrastructure code (windows service) and application code. This is
|
|
generally considered a "bad thing" but you can certainly disagree.
|
|
</para>
|
|
<para>
|
|
As Spring.NET can provide an explicitly managed
|
|
initialize/destroy lifecycle for singleton objects, there is
|
|
a natural synergy with the lifecycle of a Windows service.
|
|
As such, it could be very convenient to expose a Spring application
|
|
context as a Windows service. Starting and stopping the service corresponds
|
|
to creating and destroying an application context and its
|
|
contained objects. This approach provides a high level means to
|
|
declare what objects are created and destroyed when developing
|
|
a Windows service.
|
|
</para>
|
|
<para>
|
|
To do that, Spring.NET requires the installation of one physical
|
|
service able to run as services as many applications as you want - each a
|
|
logical independent service in their own application domain.
|
|
By default, the deployment and updating of the service can also
|
|
be done by copying the relevant executables to a special directory.
|
|
</para>
|
|
<para>
|
|
The executable that at present provides these features is the
|
|
<literal>Spring.Services.WindowsService.Process.exe</literal>
|
|
assembly. It makes heavy use of classes and interfaces definde in
|
|
the <literal>Spring.Services.WindowsService.Common.dll</literal>
|
|
assembly. You should reference the common assembly it if you want to
|
|
follow the advice on customization contained in the following sections
|
|
</para>
|
|
<para>
|
|
The benefits of this approach, a part from those given by separating
|
|
infrastructure code and application code (a field where Spring.NET
|
|
tries hard to succeed) is that you can think about installing a new
|
|
service at client site by simply dropping a new application assembly
|
|
in a remote directory<footnote></footnote>.
|
|
</para>
|
|
</sect1>
|
|
|
|
<sect1>
|
|
<title>The <literal>Spring.Services.WindowsService.Process.exe</literal> application</title>
|
|
<sect2>
|
|
<title>Installing</title>
|
|
<para>
|
|
The installation can be done in two ways, using the .NET SDK
|
|
<literal>installutil.exe</literal> tool or using the more mundane
|
|
<literal>Spring.Services.WindowsService.Installer.exe</literal>;
|
|
while the former is the standard, the latter is probably
|
|
more flexible. It allows you to customize the name/display name of the
|
|
service and has the ability to install multiple times the same assembly
|
|
with different names. This can be useful in a
|
|
number of scenarios, especially where you don't like, for some
|
|
reasons, to run several different logical services under the
|
|
same physical windows service.
|
|
</para>
|
|
<para><emphasis>
|
|
Be aware of the fact that the service will be installed as
|
|
running with the system account (installing with a specific
|
|
user account seems a bit buggy on Windows XP)
|
|
</emphasis></para>
|
|
<para>
|
|
That said, while <literal>installutil</literal>
|
|
<ulink url="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cptools/html/cpconinstallerutilityinstallutilexe.asp">
|
|
<citetitle>is documented on its own </citetitle></ulink>,
|
|
the command line for
|
|
<literal>Spring.Services.WindowsService.Installer.exe</literal>
|
|
is as follow:
|
|
<programlisting>Spring.Services.WindowsService.Installer.exe
|
|
|
|
usage:
|
|
install service-exe-path service-display-name service-name
|
|
uninstall service-name [i|u] service-exe-path service-display-name service-name</programlisting>
|
|
for example, to install, you can invoke it with the following:
|
|
<programlisting>... install Spring.Services.WindowsService.Process.exe "Spring.Service Support" spring-service</programlisting>
|
|
and to uninstall it:
|
|
<programlisting>... uninstall spring-service</programlisting>
|
|
</para>
|
|
</sect2>
|
|
<sect2>
|
|
<title>Configuration</title>
|
|
<para>
|
|
The standard .NET <literal>.config</literal> file
|
|
can be used to tune some parameters of
|
|
<literal>Spring.Services.WindowsService.Process.exe</literal>,
|
|
(including log4net settings, for which it is recomended to consult
|
|
the log4net documentation).
|
|
</para>
|
|
<para>
|
|
This file also define the context run by this process; here the file in its current beauty:
|
|
<programlisting language="xml"><configuration>
|
|
|
|
<configSections>
|
|
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
|
|
<sectionGroup name="spring">
|
|
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
|
|
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
|
|
</sectionGroup>
|
|
</configSections>
|
|
|
|
<spring>
|
|
<context type="Spring.Context.Support.XmlApplicationContext, Spring.Core">
|
|
<resource uri="file://~/service-process-definition.xml" />
|
|
</context>
|
|
</spring>
|
|
|
|
<system.runtime.remoting>
|
|
<application>
|
|
<channels>
|
|
<channel ref="http" port="1234" />
|
|
</channels>
|
|
</application>
|
|
</system.runtime.remoting>
|
|
|
|
<log4net>
|
|
<!-- see http://logging.apache.org/log4net/release/manual/introduction.html -->
|
|
<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
|
|
<layout type="log4net.Layout.PatternLayout">
|
|
<conversionPattern value="%d [%t] %-5p %c{1} - %m%n" />
|
|
</layout>
|
|
<file value="logs/Spring.Service.Process.log" />
|
|
<appendToFile value="true" />
|
|
<maximumFileSize value="500KB" />
|
|
<maxSizeRollBackups value="5" />
|
|
</appender>
|
|
<appender name="OutputDebugString" type="log4net.Appender.OutputDebugStringAppender">
|
|
<layout type="log4net.Layout.PatternLayout">
|
|
<conversionPattern value="%d{HH:mm:ss,fff} %-5p %c{2}(line:%L) - %m%n" />
|
|
</layout>
|
|
</appender>
|
|
<root>
|
|
<level value="OFF" />
|
|
</root>
|
|
<logger name="Spring.Services">
|
|
<level value="ALL" />
|
|
<appender-ref ref="RollingFile" />
|
|
<appender-ref ref="OutputDebugString" />
|
|
</logger>
|
|
</log4net>
|
|
|
|
</configuration></programlisting>
|
|
</para>
|
|
<para>
|
|
As you see, the context is defined in another file: let's review the objects it defines.
|
|
</para>
|
|
<para>
|
|
Firstly, it is worth notice that in order to 'localize' the service (i.e. to know where it is installed to use that directory as
|
|
base for the deploy dir as in the above file) you should define an object like this: the name is not
|
|
very important, it is important that it is an <literal>IObjectFactoryPostProcessor</literal> and so will be
|
|
automatically applied to this application context:
|
|
|