1. To remove from one country or region to another, with a view to
residence; to change one's place of residence; to remove; as, the Moors who
migrated from Africa into Spain; to migrate to the West.
2. To pass periodically from one region or climate to another for feeding or
breeding; -- said of certain birds, fishes, and quadrupeds.
Webster’s Revised Unabridged Dictionary

Introduction

This article presents steps required to migrate Windows service applications
(also called NT services) written using Visual C++ 6.0 and ATL to Visual
C++.NET. Most of ATL and MFC code requires only recompilation when upgrading
Visual Studio from version 6.0 to .NET. Unfortunately, this is not the case
with ATL service applications. Part of ATL7 that handles Windows services has
been rewritten, so most of the code that ATL Wizard generated in Visual C++ 6.0
is no longer needed – actually, the code is still in use, but it has been moved
to ATL classes rather than being copied by Wizard to every service application
you create. The downside of this improvement is that it breaks applications
that were written using ATL3 (the version that came with Visual C++ 6.0).

So what should you do if you have a service application that no longer works
after rebuilding with Visual C++ .NET? You have three main options:

Rewrite the whole application in C# (hey, isn’t it cool?)

Keep a copy of Visual C++ 6.0 – just to maintain you service applications.

Make necessary changes to make your code compatible with ATL7.

First option is not as attractive as it may look at first glance. Windows
service applications are often written to manage low-level resources, including
hardware. Its source code is frequently dependent on third party libraries –
usually "C" libraries. Such applications need to be debugged very thoroughly
(comparing to UI programs), and once the code is stable, it usually lasts long.

The second option is the cheapest one in terms of team resource allocation, but
it is kind of cheap in other terms too. Doesn’t it irritate you as a developer
if you need to give up with a problem (probably a minor one) instead of fixing
it?

So we’ll take the third approach: we'll fix it! As you are going to see, this
choice will not only correct program behaviour, it will also improve and
simplify the source code.

Phase 1. The meaning of life

Yes, you’ve finally found the meaning of life, and you want to tell the rest of
the world about it. Perhaps, those who have read Douglas Adams’ books already
know the answer (42, remember?), but at you find their number insufficient. So
you build a simple Windows service application using Visual C++ 6.0 and ATL. It
takes just a few minutes, and your service is up. I have included a Visual C++
6.0 workspace that contains ATL service source code and a test command-line
application. Here are the highlights of the project:

The service is called MyService1. Use commands "net start
MyService1" and "net stop MyService1" to start and stop
the service from a command line prompt, or you can use Control Panel "Services"
applet.

Before you can start the service, you should register it by issuing a command "MyService1 /Service" (when ATL Wizard generates service code, it
does not include service registration in custom build step).

The application also includes an interface (IMeaningOfLife1) and
its implementation in a coclass MeaningOfLife1. The only method
(read-only property) that the interface has is MeaningOfLife, and
of course it returns 42 as it should.

Since the application does not have thread affinity, it’s implemented as
free-threaded.

The project code for this sample service is included with this article (project
MyService1).

Phase 2. Problem

Your service works very well, there are thousands of people who find the meaning
of life every day, and you have new ideas (perhaps, less philosophical, but
this time giving you a sign of income). You’re hungry for new technology, and
you love .NET from the first sight. So you install Visual Studio.NET, and
recompile all your projects. When you are about to free some disk space and
consider Visual Studio 6.0 as a best candidate for such purpose, you discover
that there’s one application that did not survive tools upgrade: your famous MyService1
that serves MeaningOfLife to the masses. You would like to debug
the application, but can’t even start it as a service! And when you connect to
MeaningOfLife component from a test client, it works just fine.
Something is definitely broken at service level.

Phase 3. Analysis

ATL3 (which was shipped with Visual Studio 6.0) had full support for Windows
services, but service handling code really lacked encapsulation. If you ran ATL
Wizard and generated service code, you could discover the following:

Header file "stdafx.h" did not only include necessary system
headers, it also contained full declaration for a class CServiceModule
that was (and had to be!) inserted between references to "atlbase.h"
and "atlcom.h". Not the best place to declare new classes!

The main service C++ file contained of more than 400 hundred lines of code that
implemented CServiceModule functions. You wouldn’t be changing
most of these functions even if you needed to customize the service (why would
you need to change FindOneOf, Lock or LogEvent?)
What you would typically need is to be able to add custom steps to service
initialization and termination. Unfortunately, you would have to modify
directly CServiceModule::Run(). I wrote several Windows services
using ATL3 and all of them had very similar CServiceModule code,
that differed only by class GUIDs and calls to custom initialization routines
from inside CServiceModule::Run() method.

The part of ATL7 that handles Window services have been completely redesigned in
Visual C++.NET. Similar to other ATL classes, service module has been turned
into a template CAtlServiceModule with major functionality
implemented inline in ATL headers. What happens now if you leave your old code
unmodified, is that your service will contain an old version of CServiceModule
code (as generated by ATL Wizard), while ATL headers have its own – an improved
one. What becomes a real problem is that the new implementation is not
compatible with the old one. Fortunately, it’s easy to fix. Migrating your
Windows service code becomes more or less removal of hundreds of lines that ATL
Wizard used to inject into your project.

Phase 4. Solution

Now that we know what caused the problem and that it’s easy to fix (at least
according to the promise), let’s do it. I included a new version of MyService1
application (this time named MyService2, so they can coexist). I
highlighted some of the changes that were necessary to make so the new version
could work. I also listed some simple changes that improve code quality.

Some of the functions in ATL registry classes have been deprecated (and
replaced with new ones that are strongly typed). You should replace calls to SetValue
and QueryValue with SetStringValue and QueryStringValue
respectively.

Now the major step. Remove CServiceModule declaration from "stdafx.h".
Let ATL7 use the most recent one!

Remove CServiceModule implementation from your service C++ file.
This step requires some accuracy, because you have probably included custom
service initialization and cleanup code (remember CServiceModule::Run()
method). You should move this code to methods CServiceModule::PreMessageLoop
and CServiceModule::PostMessageLoop that ATL7 offers now. So your
service module class declaration should be like this:

And service initialization and cleanup routines (PreMessageLoop and
PostMessageLoop) will contain whatever custom steps you need.

If you now rebuild your service (and register it using "MyService2 /Service"
command), it will successfully start and stop. Ironically, if you then test MeaningOfLife
component using supplied client application, it will fail to instantiate it
throwing infamous 0x80080005 result code ("Server execution
failed"). Further research led me to additional changes:

You should start using new OBJECT_ENTRY_AUTO macro instead of
traditional object maps (wrapped by BEGIN_OBJECT_MAP and END_OBJECT_MAP).
So remove the following code from your service implementation file ("MyService2.cpp"):

Last but not least. Do you remember that your application is free-threaded?
That’s another catch: ATL7 CAtlExeModuleT::PreMessageLoop has a
bug that prevents service to create free-threaded components (when the
application is launched as a service). I was not able to find a knowledge base
article on this topic, but one Microsoft employee was kind enough to post a
workaround in a newsgroup (search Google for PreMessageLoop
and CoResumeClassObjects). Finally your PreMessageLoop/PostMessageLoop
methods should look like this:

Source code for updated (VC++.NET friendly) version of the sample Windows
service is included with this article (project MyService2).

Phase 5. The meaning of attributed life

Let’s face it now. Your new code looks more elegant now – it is much shorter, it
only implements application-specific functions, and – for those who appreciate
it – it is object oriented. But since you already used ATL7 new features, maybe
there’s something else you could use that would make your code even more
compact and manageable. Yes, your code still inherits ATL3 source file
structure, i.e. it contains:

IDL file with interface and type library declaration;

RGS files with duplicates of coclass, type library and service GUIDs;

C++ header and implementation files with coclass and service class declaration
and implementation (although radically reduced in size comparing with ATL3).

What’s wrong with this structure? Of course, this is not just number of files.
What makes it harder to manage is that different files must include duplicate
information (like interface methods and GUIDs). And while changing interface
without updating its implementation will result in compiler error (and will be
addressed), if you forget to update GUID value in all places it is included,
you will end up in Registry hell that is not much different from DLL hell (hell
is hell after all!)

Welcome to attributed programming! By adding ATL attributes you will make your
code even more compact and manageable. Attributes are really simple – they
provide functionality similar to macros in ATL3, but they are smarter. A macro
only affects things in-place (i.e. wherever it is inserted), being a C++
creature it has no control over other parts of a program, even though several
places need to be updated simultaneously. An attribute is not limited to a
single piece of code – a single attribute can trigger generation of a source
code, resources and registry script. Therefore use of attributes helps you
write less code with less risk of making it inconsistent.

If you feel motivated for attribute programming, you can now make the following
changes to your application:

Select project properties, highlight General configuration properties,
and for entry Use of ATL choose Static link to ATL.

Add _ATL_ATTRIBUTES to preprocessor definitions.

Select Embedded IDL in Linker category and specify name base for Merged
IDL Base File Name entry. For example, if you choose _MyService.idl,
it will cause _MyService to be used as a base name when generating
proxy/stub and type library files.

Select MIDL category and choose Yes for Generate stubless proxies.

Remove from your project IDL file and coclass RGS file(s) – these files are no
longer needed! (Keep service RGS file as the only RGS file in your project).

You should also remove OBJECT_ENTRY_AUTO line – attributes will
take care of it.

Conclusion

Our initial effort was made simply to fix problems with incompatibility between
ATL3 and ATL7 Windows service applications. However, use of new ATL features
also helped us to reduce both the number of project files and its code size. If
we count only significant project files (leaving out auto-generated that don't
require manual maintenance), we'll get the following figures:

MyService1 (ATL3): 10 files, 19851 bytes

MyService2 (ATL7, no attributes): 10 files, 9485 bytes

MyService3 (ATL7, with attributes): 8 files, 6987 bytes

Even though we had to deal with ATL incompatibility issues in our Window service
application, the final result was worth the effort. ATL7 takes from you most of
the job of keeping your code consistent and readable, so you can save your
creativity for more important tasks.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Vagif Abilov is a Russian/Norwegian software developer and architect working for Miles. He has more than twenty years of programming experience that includes various programming languages, currently using mostly C# and F#.

Vagif writes articles and speaks at user group sessions and conferences. He is a contributor and maintainer of several open source projects, including Simple.Data OData adapter, Simple.OData.Client and MongOData.

Vagif,
I have a question on control the servce of Window.
I am using VC ++ 6.0 and devloping MFC program now.
When the user launch my application, the application
needs to check the service named SV2000. If the service is started,
the application has to set it to stop state.
When the application exit, it has to set the service to started.
How can I do it ? Do you have example code ?
I am new on this

Hi ,
i'm stuck in really strange problem.
I'd devloped a windows service using above method in VC++.net. This service has an interface exposed.
I'm facing following problems.
1)In installer code of .net i used command "servicepath" -service to install the service.
at this point service installs and starts(as it is created in automatic mode).
But when i tried to access that interface throught other windows application ,it gives error,'queryinterface on object failed'.
If i unregisters same service from command line and registers it using same command,it works fine.
what would be problem.
2) what would be ideal installer for this service?how to achive that?
thanks ,
prasad

thanks, this solved my problem.
Now i dare to tell you some more problems,
1.
by default service created is in manual mode, to make it automatic i'd overriden function Install to create service in automatic mode,
I've overridden RegisterAppId to call this install function.
Now when i installs service it starts in auto mode.
But i observed one thing, after rebooting for three or four times on windows2000 server,it fails to start on reboot.
But if i try to start it manually it works fine.
2.
after installation my service start in auto mode.
If stops and starts again.it works fine.
but if i unintalls it it become disabled(mark for deletion). Can i supress this behaviou?
thanks,
Prasad

I was really happy to find out why my perfectly working ATL3 service would not work with ATL 7. Thanks Vagif.
I rushed to copy/paste this code
#if _ATL_VER == 0x0700
if (SUCCEEDED (hr) && !m_bDelayShutdown)
hr = CoResumeClassObjects();
#endif
into my file and was surprised again - it still would not work. After a few minutes it dawned on me that it should be #if _ATL_VER >= 0x0700 because I am using ATL 7.1.
That is my 5 cents.

My VC6 generated windows service project supported MFC. But after migrating my code to ATL7 as you suggested I noticed that I can't use MFC any more. As soon as I include AFXWIN.h in the stdafx.h file I get this compile error in my server.cpp file:

"error C2504: 'CAtlServiceModuleT' : base class undefined"

If I remove afxwin.h from stdafx.h file then it compiles ok but then I have no MFC support. A lot of my code depends on MFC and it also links with other MFC DLLs so I can't really get rid of MFC. Is there a way to make ATL7 to co-exist with MFC? And why would Microsoft stop supporting that without notice!?

No one replied to this post so I decided to do my own research. Since ATL7 has a lot of the functionality of MFC built into it, including the two libraries in your StdAfx.h file can cause the compile problem. To fix it first make sure to include MFC header files BEFORE including ATL headers, and then just add a "#undef _AFX" after the MFC header files, like shown below:

I had this same problem...
And the easiest way to solve this was to create a new version of atlbase.h
without the _afx define arround CAtl...ModuleT!
I was able to craft a solution using the #undef _AFX but it only worked when i was not
using attributed code!
The main problem I see with this solution is that there must be a vaslid reason for the #ifdef _AFX, but until now the services are running fine using some classes from the MFC library!

In Visual Studio .NET 2003, this method is not implemented in the base class. The Visual Studio project wizard includes this method in the generated code, but a compilation error will occur if a project created in an earlier version of Visual C++ is compiled using ATL 7.1. Any class that derives from CAtlServiceModuleT must implement this method in the derived class. The method has to call CoInitializeSecurity and provide the appropriate security settings for the service.

Use PKT-level authentication, impersonation level of RPC_C_IMP_LEVEL_IDENTIFY and an appropriate non-null security descriptor in the call to CoInitializeSecurity.

Hi Vagif,
Thanks very much for you article, it was very useful for me.
I have a question to you though... I need to change the description of the service and I used to do it in Install() method in VS6. But it looks like that I can't override the Install() method from CAtlServiceModuleT. I would be greatful for any idea on what's the best place for this configuration changes...
Thank you

The problem of this article is in the Migrating ATL applications to Visual C++.NET because there is a bug during the compilation.
The file atlapp.h don't exist in Visual C++.NET and I can't find good informations on this subject.

1. I create a ATL service in VC++ 6.0. call the com object in Vb application.
My problem is :- when I terminate the Vb application autometicaly my service has killed. my requirment is my service is running contiounsly until my system is reboot or userkill manulay?

Your problem is that event though your create your application as a service, unless you register and start it properly, it can still be instantiated as a regular out-of-proc COM component, i.e. it will terminate when client is finished with it.

Make sure you register your service by running " -Service" command. AFAIK, ATL6 has a bug there, so you have to register service after registering COM objects (-RegServer option). Then start a service either from ControlPanel or by issuing "net start " from a command prompt.

Hope this helps.

Вагиф АбиловMCP (Visual C++)
Oslo, Norway

Hex is for sissies. Real men use binary. And the most hardcore types use only zeros - uppercase zeros and lowercase zeros.
Tomasz Sowinski

I have done the said steps for installing the sample as Windows service on XP.
But when i call the service object thru client1 app, the service stops responding and i cannot start or stop. when i try net start , i get this" The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.". How to avoid the service from becomg like this ?

Great article, but one question refering the ATL7 Service (samples are hard to find, maybe someone could send something...(j.voskuil@wanadoo.nl) I need to write a service that must process a text file every 5 min. So I must create a loop. But's a service, so there must be a processing loop (RunMessageLoop????). I can't find where i must put my code.

Hi Vagif! Unfortunately the MyService2 - Project you are talking about in your article can't be build. There are some missing files like "MyService2.h" and trying to build proxy/stub (nmake -f MyService2ps.mk) ends with fatal error U1073: don't know how to make 'dlldata.obj'. Sorry... I'm not sure you have checked this project before posted to the web.

I always verify projects before posting them to the Web. I wouldn't waste your time on project that can't be built But there is an assumptions I make - I assume you will be using Visual Studio .NET to build the project. The file that you refer to (MyService2.h) does not belong to the source code. This file is automatically generated when you run MIDL compiler on MyService2.idl. MIDL produces several files that are used to generate output binaries. So you can't just run nmake on MyService2ps.mk without running MIDL first. I suggest you load MyService2.sln into Visual Studio .NET and build it. It should solve your problem.

Best regards

Вагиф АбиловMCP (Visual C++)
Oslo, Norway

Hex is for sissies. Real men use binary. And the most hardcore types use only zeros - uppercase zeros and lowercase zeros.
Tomasz Sowinski

In vc 6.0, to do this , just include "afxtempl.h" before "atlbase.h" and use MFC in shared dll.But, In VC.net, I found this can not work, It wiil give an compile error "the symbol of CAtlServiceModultT can't be found".