The Perfect Service - Part 1
page 1 of 2
Published: 29 Dec 2005
Unedited - Community Contributed
In this article, Ambrose illustrates how to use a drag-n-drop/xcopy .NET Windows services manager that can make your life a lot easier if you find yourself needing to implement multiple Windows services in your enterprise. The next article in the series goes into some depth, exploring how the service manager works so that you can take those concepts and apply them in your own development.
by J. Ambrose Little
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 21973/ 71


Note: This article was originally published in June 2004 on, but it has gotten good reviews, and the techniques, I believe, are still valid. I hope the readers of ASPAlliance find it as useful as I have.

[Download Code]

I was hanging out with some local user group types last night when the "Perfect Storm" (the movie based on a severe storm in 1991) came up. Since I was just talking about this very flexible Windows service I had written, it suddenly came to me to name the article about it "The Perfect Service." Of course, this is not to say that it is indeed the perfect service, but all the same, I thought it sounded really good at the time (or maybe that was the Scotch...).

In any case, this article is the first in a two part series that covers first how to use the "perfect service" and then explores the details of how it works. The first part covers the details of how to get the service running and then how to add plug-n-play services to it. The second part will explore the details, which includes the use of advanced topics such as loading and unloading application domains, using .NET Remoting, and using reflection.

I realize that I am not the first, nor will I likely be the last, to attempt such a feat. In fact, I've referenced two other articles covering more or less the same goal in the resources section. However, I believe that this particular implementation is superior in its ease of use and flexibility.

First off, I need to discuss terminology. This is necessary because for some reason the English language does not offer too many alternatives to the word "service" in the way that we mean it when we talk about Windows services, Web services, services in service-oriented architecture, and the like. I think the best alternative that isn't overloaded in the IT world is "ministration," and while I'm all for complicated-sounding words, I think I'll just stick with the industry term to describe the concept I am referring to and use a modifier to clarify when necessary.

The new concept I'm introducing is related to the title of my Windows service, which is ".NET Service Manager." This Windows service essentially provides you with drag and drop or XCOPY deployment of what would normally have to be installed as individual Windows services in themselves. Basically, any long-running or timed process that you want to be run even when a user is not logged in qualifies as a candidate for a Windows service.

Unfortunately, Windows services, even in .NET, are not the easiest thing to implement, and you have to manually install them and start and stop them using the Services MMC snap-in. This basically involves a fair amount of drudgery and, if you have many processes like this, can make your services list become unfriendly.

Enter the .NET Service Manager. This application enables you write, install, and start (using the MMC snap-in) the Windows service just once. At that point, you are ready to do some real work, using the same (or better) XCOPY story that, for instance, ASP.NET has. By simply applying an assembly attribute and implementing a simple interface, you can enable any .NET code library (DLL) assembly to run under the .NET Service Manager. I've decided to call such assemblies "managed services," which simply means they act like a Windows service but are managed by the .NET Service Manager.

For the most part, in this series, when I refer to a "service," I will qualify it as either a Windows service (formerly known as "NT service") or managed service, which indicates the kind of service described in the previous paragraph. This article will cover the details of implementing a managed service, so you can take away from it the ability to use the .NET Service Manager and all the conveniences it provides without having to know how it works. The next part will cover how all of this is made possible.

Not only does the .NET Service Manager enable you to install and start a service by simply copying it to the process directory, it also enables you to update it on the fly (using the same deployment mechanism) without needing to stop or start the service manager itself. Doing this will not affect the other managed services because they are all running in their own application domains, and it is not necessary to stop the service manager itself. Similarly, you can stop an individual managed service by removing (deleting or moving) its DLL from the service process directory-so uninstalling is as easy as installing.

Further, you may be aware that .NET does not support config files for code libraries. There are some good reasons behind this, but I have found numerous occasions where having this capability would be quite handy. Managed services are one of them, so I've enabled an easy-to-use interface for storing settings in an app.config-like file (e.g., SampleService.dll.config) that follows the same conventions as a typical config file with app settings. We will also cover an example of implementing this technology.

There are only two steps required to enable your code to run as a managed service:

  1. Implement the ServiceBroker.IService interface on one of your types.
  2. Apply the ServiceBroker.ServiceEntryPointAttribute to your assembly, using it to specify a display name for the service and the type that serves as the service entry point-this must be a type that implements the interface from Step 1.

There is an optional third step that you can use to take advantage of the config file capabilities, but you only need this if your managed service requires any configurable settings. All three of these will be covered in this article.

You will, of course, also need to have a reference to the ServiceBroker.dll assembly. It is installed with the .NET Service Manager, so you can just reference it in the installation directory (e.g., C:\Program Files\Littlechip\.NET Service Manager\) or copy it to some other common assembly reference directory as demonstrated in the article "Where's My Assembly?" and reference it there.

View Entire Article

User Comments

Title: re: Could not load type 'SampleService.Test'   
Name: tom
Date: 2009-04-10 6:49:04 PM
I was getting the same error as the other 2 posters and
found a fix that 'works on my machine':

SampleService project - AssemblyInfo.cs

the fix:
[assembly: ServiceBroker.ServiceEntryPoint("SampleService", typeof(SampleService.Test))]


and it worked.
Title: Mr   
Name: Andre
Date: 2009-04-03 7:39:47 AM
Tried exactly the same with the same tools and got the Same Error, but with the following stack trace:
StackTrace Information

Server stack trace:
at System.RuntimeTypeHandle._GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName)
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
at System.RuntimeType.PrivateGetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
at System.Type.GetType(String typeName, Boolean throwOnError)
at ServiceBroker.ServiceEntryPointAttribute..ctor(String serviceName, String entryPointTypeName)
at System.Reflection.CustomAttribute._CreateCaObject(Void* pModule, Void* pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
at System.Reflection.CustomAttribute.CreateCaObject(Module module, RuntimeMethodHandle ctor, IntPtr& blob, IntPtr blobEnd, Int32& namedArgs)
at System.Reflection.CustomAttribute.GetCustomAttributes(Module decoratedModule, Int32 decoratedMetadataToken, Int32 pcaCount, RuntimeType attributeFilterType, Boolean mustBeInheritable, IList derivedAttributes)
at System.Reflection.CustomAttribute.GetCustomAttributes(Assembly assembly, RuntimeType caType)
at System.Reflection.Assembly.GetCustomAttributes(Type attributeType, Boolean inherit)
at ServiceBroker.RemoteServiceHandler.LoadService(String assemblyName)
at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
at System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(RuntimeMethodHandle md, Object[] args, Object server, Int32 methodPtr, Boolean fExecuteInContext, Object[]& outArgs)
Title: Could not load type 'SampleService.Test'   
Name: Cameron
Date: 2008-11-10 11:03:29 PM

I followed the article and compiled the source code with no errors, installed the .net Service Manager successfully.
My projects are pointing to framework 2.0 and are compiled using C# 2008.

When I drop in the SampleService.dll and SampleService.dll.config where the service is running the Application event log raises the following (plus stack trace not included).

Exception Type: System.TypeLoadException
Message: Could not load type 'SampleService.Test' from assembly 'ServiceBroker, Version=1.0.604.0, Culture=neutral, PublicKeyToken=null'.

Any ideas?

Community Advice: ASP | SQL | XML | Regular Expressions | Windows

©Copyright 1998-2017  |  Page Processed at 2017-03-23 4:15:25 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search