Introduction
Struggling to start with the basics of Windows Services? This little project will provide you with a very simple background process class in C++ that can be used right away for creating a Service.
Please note that the exact purpose of this example is to encapsulate all details for novice programmers so they just can get started with writing a service right away. This is not a walk through on lower level how to write a service. All of that has been encapsulated in the JDMBackgroundProcess
class and has been described already in the article Simple Windows Service in C++[^].
This article is an alternative approach to the first article.
Background
There are not many Windows Service examples in C++. A useful one that I found is located here: http://www.codeproject.com/Articles/499465/Simple-Windows-Service-in-Cplusplus.
However I wanted a solution with an ANSI C++ interface that could be very easily integrated with existing source code. I have written a wrapper class called JDMBackgroundProcess
with a very simple interface that could do this trick. It also encapsulates all Windows specific code so it can be extended to other operating systems as well (for example Linux Daemons).
Using the Code
Let's go straight to an example of how we can change a normal executable program to start acting as a service. All we have to do are a few simple steps:
- Add a
JDMBackgroundProcess
object to your main function and provide a new "Main
" function. - Call the
StartInBackground()
function of the JDMBackgroundProcess
object. - Report to
JDMBackgroundProcess
object that your "Main
" function is running. - Check the status of the service regularly and exit your "
Main
" function when the service is being stopped.
Let's clarify this with a main
function below:
static int JDM_BGP_CALL_CONV Main(int argc, char* argv[]);
static void JDM_BGP_CALL_CONV ExtraPauseFunction();
static void JDM_BGP_CALL_CONV EventNotifier(JDM_BGP_EVENTS EventCode);
JDMBackgroundProcess* pBGP;
int main(int argc, char* argv[])
{
long RetVal=-1;
JDMBackgroundProcess BGP(".ProcessName", "ProcessDescription", Main, EventNotifier);
pBGP=&BGP;
if(argc>1) {
if(!_stricmp("debug", argv[1])) {return BGP.StartInForeground(argc, argv);}
else if(!_stricmp("install", argv[1])) {return BGP.Install(argc, argv);}
else if(!_stricmp("create", argv[1])) {return BGP.Install(argc, argv);}
else if(!_stricmp("uninstall", argv[1])) {return BGP.Uninstall(argc, argv);}
else if(!_stricmp("delete", argv[1])) {return BGP.Uninstall(argc, argv);}
}
RetVal=BGP.StartInBackground();
return RetVal;
}
As you can see, a BGP
object with a chosen process name and process description gets created and a function pointer to a new "Main
" function is provided. At the end of the main
function, we will call the StartInBackground()
function to let the service interact with the operating system.
The event notifier function is optional. The process name and process description will be visible in the services management console of Windows.
Now let's see the newly provided "Main
" function (which can be a copy of the old main function of your program with some small additions):
static int JDM_BGP_CALL_CONV Main(int argc, char* argv[])
{
if(pBGP->IsStartedInForeground()==true) {
cout << "Press <CTRL>+Break to PAUSE, <CTRL>+C to RESUME and close window to STOP" << endl;
}
pBGP->ReportRunning();
while(pBGP->StopReceived()==false) {
cout << "run" << endl;
pBGP->CheckAndHandlePauseResume(1000, &ExtraPauseFunction);
Sleep(1000);
}
cout << "stop" << endl;
Sleep(1000);
return 0;
}
Basically, what should be added is a call to pBGP->ReportRunning()
to report to the JDMBackgroundProcess
that we have started our program.
Further on, we check by pBGP->StopReceived()
if the operating system has requested for the service to be stopped, and if so we will exit our "Main
" function. Also we check if the service needs to be paused by pBGP->CheckAndHandlePauseResume()
.
That's all there is to it, I could not think of a more simple solution than this.
The latest source code can be downloaded at https://sourceforge.net/projects/jdmbackgroundprocess/.
History
- 2014-09-24: Removed empty "Download source (no EXE)", updated a typing mistake in the comments of the source code, updated the download file with the latest sources.
- 2014-06-15: Added additional text to the Introduction paragraph
- 2014-06-13: Added example source code at top of the page in addition to the SourceForge link
- 2014-06-12: Initial version