Click here to Skip to main content
Click here to Skip to main content

A Windows Service Application

By , 29 Nov 2006
 

Introduction

Recently, I came across a situation where I needed to make an application launch automatically when the PC starts up. And the problem was that the program that I needed to launch was designed as a GUI application. The best way I could think of to make it launch automatically was to create a service based application, so that once the user logs on to the computer, the application would be executed automatically by the service and monitor the application. Then, I thought of appending more than one application into a service and run it till the service is killed or stopped.

Background

I searched a number of sites for some code that could help me create a simple Windows service application which can fork and monitor some applications, but I only found a lot of code on how to manage the current Windows services on the system. Later, I started to create my own with the help of MSDN.

Description

This is a simple Windows based services application which is created using Win32 - VC++. The usage of this application is - it will act as a Windows service which is able to fork and monitor any number of sub processes which are running under this service. The applications can be of any type like GUI, non-GUI etc.

This application will help you know about the following topics related to a service application:

  1. How to create/install a new Windows Service.
  2. How to map some applications to a particular Windows Service, and control the application by the service. (How to connect to the Control Service Manager.)
  3. How to start/run Window services.
  4. How to stop/kill Window services.
  5. How to uninstall Windows services.

Code Usage

The code is very simple, and for the most part, self-explanatory. The application executable is given the name "WinService.exe". The user has to pass some command line arguments while executing this application, through the command prompt to make use of its different features.

""ApplicationName  FeatureExtension"

Note: The default service name would be "Sundar_Service". The user can change the service name in the code and rebuild the application.

Feature Extensions

ApplicationName -i  / -I - Create / Install New service
ApplicationName - Connect to Service Control Manager
ApplicationName -s / -S - Run / Start the service
ApplicationName -k / -K - Stop / End the service
ApplicationName -u / -U - Uninstall / Kill the service from windows

Create / Install New Service

"WinService -i" or "WinService -I"

Sample Image

When you type the above line on the command prompt and press Enter, you are able to view a new service in the Windows Services window with the name "Sundar_Service".

VOID Install(char* pPath, char* pName);

The Install method creates a service object and adds it to the specified service control manager database.

SC_HANDLE schService = CreateService(
            schSCManager,     /* SCManager database      */
            pName,            /* name of service         */
            pName,            /* service name to display */
            SERVICE_ALL_ACCESS,  /* desired access       */
            SERVICE_WIN32_OWN_PROCESS|
              SERVICE_INTERACTIVE_PROCESS , /* service type  */
            SERVICE_AUTO_START,   /* start type              */
            SERVICE_ERROR_NORMAL, /* error control type      */
            pPath,                /* service's binary        */
            NULL,                 /* no load ordering group  */
            NULL,                 /* no tag identifier       */
            NULL,                 /* no dependencies         */
            NULL,                 /* LocalSystem account     */
            NULL        );        /* no password             */

Sample Image

Connect to SCM (Service Control Manager)

"WinService" or "WinService"

Sample Image

While executing the above command on the command prompt, the child processes which are mapped under the service "Sundar_Service" will get started. And these processes will be monitored by the service, so that the application can be started again if it gets killed for any reason.

VOID ExecuteSubProcess();

The "ExecuteSubProcess" method is defined with the "_beginthread" method for thread creation, which ensures the child process continues execution till the service is stopped by the user or Windows. This will also call the "StartServieCtrlDispatcher" method.

if(!StartServiceCtrlDispatcher(lpServiceStartTable))

The "StartServiceCtrlDispatcher" connects the main thread of a service process to the service control manager, which causes the thread to be the service control dispatcher thread for the calling process.

VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)

The callback functionality mapped through the lpServiceStartTable structure will register the "ServiceHandler" method to the service and update its status. Also, this will execute its child applications.

VOID WINAPI ServiceHandler(DWORD fdwControl)

The "ServieHandler" method will control service functions, like "Start", "Stop", "Pause" etc.

Note: Child applications are attached as "1.exe", "2.exe", "3.exe", and "4.exe" where the user can update or change the application. This sample application will animate an icon on the system tray of Windows.

Run / Start Service

"WinService -s" or "WinService -S"

Sample Image

When the above line is executed on the command prompt, the service "Sundar_Service" will be started.

VOID RunService(char* pPath, char* pName)

The user-defined RunService method will use the "StartService" method to start a service after getting the service control manager control handle and the service handle.

if(StartService(schService, 0, (const char**)NULL))

Sample Image

Sample Image

Stop / End Windows Service

"WinService -k" or "WinService -K"

Sample Image

This command will stop the service by sending the "SERVICE_CONTROL_STOP" control code to service the control manager using the "ControlService" method. This will lead to executing the user case functionality in the "ServiceHandler" method to stop the service.

if(ControlService(schService,SERVICE_CONTROL_STOP,&status))

Uninstall / Kill the Service from Windows

"WinService -u" or "WinService -U"

Sample Image

This command will uninstall the service from the Windows Service Manager database, after all its child processes have been stopped.

if(!DeleteService(schService))

The "DeleteService" method marks the specified service for deletion from the service control manager database.

Sample Image

Logger

Sample Image

VOID WriteLog(char* pFile, char* pMsg)

The "WriteLog" method would log all the errors and the status of the service in the application path as "Sundar_Service.Log", with the service name as the log file name.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Shanmuga Sundar.V
Architect
India India
Member
Module Lead working in leading MNC company, india - bangalore.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionInstall Automaticallymemberrajendran_t2 May '13 - 3:04 
Great Job. It was quite easy and comfortable to understand.
 
If i install this service manually by using command prompt as administrator, i can able to see the service in services.msc
 
But could you please guide me to how to install the service using setup and deployment straight away without manually using the command prompt.
GeneralMy vote of 5mvpMichael Haephrati6 Mar '13 - 23:04 
Great job
Questionu did good job !!!memberMember 986162124 Feb '13 - 21:30 
it was very very impressive codes for me. u did good job !! Laugh | :laugh:
Questionproblem in pausemembersamira baigy14 Aug '12 - 0:33 
hi
firs of all thanks for ur useful post.
i wrote a service it have problem in pause the service! actuly when i pause the service it get changed and change to pause state but my service program dosnt pause and continue in running!!! it means that dwCurrentState get change to SERVICE_STOPPED but SCM dosnt pause my program
my handler code is:
VOID WINAPI Handler(DWORD fdwControl)
{
// State change notifications
switch (fdwControl) {
case SERVICE_CONTROL_STOP:
ServiceWriteToLog(L"Imen:function Handler has no fault In SERVICE_CONTROL_STOP\n");
//s_SvcStat.dwWin32ExitCode=0;
s_SvcStat.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(s_hSvc, &s_SvcStat);
break;
 
case SERVICE_CONTROL_PAUSE:
ServiceWriteToLog(L"Imen:function Handler has no fault In SERVICE_CONTROL_PAUSE\n");
s_SvcStat.dwCurrentState = SERVICE_PAUSED;
SetServiceStatus(s_hSvc, &s_SvcStat);
break;
 
case SERVICE_CONTROL_CONTINUE:
ServiceWriteToLog(L"Imen:function Handler has no fault In SERVICE_CONTROL_CONTINUE\n");
s_SvcStat.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(s_hSvc, &s_SvcStat);
break;
 
case SERVICE_CONTROL_INTERROGATE:
break;
 
default:
ServiceWriteToLog(L"Imen:function Handler has fault In OTHER Handler\n");
break;
}
 
return ;
}
i have seprate routin for resuming service:
bool ResumeService(LPWSTR szSvcName, DWORD dwTimeout)
{
SC_HANDLE hSCM, hService;
SERVICE_STATUS ss;
DWORD dwStartTime;

//
ServiceWriteToLog(L"\n Imen:start of ResumeService!");
__try {
 
// Open the SCM database
hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT );
if ( !hSCM ) {
ServiceWriteToLog(L"\n Imen:error in OpenSCManager!");
__leave;
}
 
// Open the specified service
hService = OpenService( hSCM, szSvcName, SERVICE_PAUSE_CONTINUE
| SERVICE_QUERY_STATUS | SERVICE_ENUMERATE_DEPENDENTS );
if ( !hService ) {
CloseServiceHandle(hSCM);
__leave;
}
} __finally {
;
}
 
if (hSCM == NULL || hService == NULL) {
if (hService) CloseServiceHandle(hService);
if (hSCM) CloseServiceHandle(hSCM);
 
return FALSE;
}
 
dwStartTime = GetTickCount();
 
// Make sure the service is not already stopped
if ( !QueryServiceStatus( hService, &ss )) {
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
ServiceWriteToLog(L"\n Imen:error in QueryServiceStatus!!!");
return FALSE;
}
 
if ( ss.dwCurrentState == SERVICE_RUNNING) {
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
 
return TRUE;
}
 
// If a stop is pending, just wait for it
while ( ss.dwCurrentState == SERVICE_CONTINUE_PENDING) {
 
Sleep( ss.dwWaitHint );
if ( !QueryServiceStatus( hService, &ss ) ) {
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
 
return FALSE;
}
 
if ( ss.dwCurrentState == SERVICE_RUNNING ) {
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
 
return TRUE;
}
 
if ( GetTickCount() - dwStartTime > dwTimeout ) {
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
 
return FALSE;
}
}
 
// Send a stop code to the main service
if ( !ControlService( hService,SERVICE_CONTROL_CONTINUE , &ss ) ) {
DWORD error=GetLastError();
switch(error)
{
case ERROR_ACCESS_DENIED:
ServiceWriteToLog(L"\nThe handle does not have the required access right.");
break;
 
case ERROR_DEPENDENT_SERVICES_RUNNING:
ServiceWriteToLog(L"\nThe service cannot be stopped because other running services are dependent on it.");
break;
 
case ERROR_INVALID_HANDLE:
ServiceWriteToLog(L"\nThe specified handle was not obtained using CreateService or OpenService, or the handle is no longer valid.");
break;
 
case ERROR_INVALID_PARAMETER:
ServiceWriteToLog(L"\nThe requested control code is undefined.");
break;

case ERROR_INVALID_SERVICE_CONTROL:
ServiceWriteToLog(L"\nThe requested control code is not valid, or it is unacceptable to the service.");
break;

case ERROR_SERVICE_CANNOT_ACCEPT_CTRL:
ServiceWriteToLog(L"\nThe requested control code cannot be sent to the service because the state of the service is SERVICE_STOPPED, SERVICE_START_PENDING, or SERVICE_STOP_PENDING.");
break;
 
case ERROR_SERVICE_NOT_ACTIVE:
ServiceWriteToLog(L"\nThe service has not been started.");
break;

case ERROR_SERVICE_REQUEST_TIMEOUT:
ServiceWriteToLog(L"\nThe process for the service was started, but it did not call StartServiceCtrlDispatcher, or the thread that called StartServiceCtrlDispatcher may be blocked in a control handler function.");
break;

case ERROR_SHUTDOWN_IN_PROGRESS:
ServiceWriteToLog(L"\nThe system is shutting down");
break;
default:
ServiceWriteToLog(L"\nnot specified error in ControlService!");
 
}
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
 
return FALSE;
}
 
// Wait for the service to stop
while ( ss.dwCurrentState != SERVICE_RUNNING ) {
 
Sleep( ss.dwWaitHint );
if ( !QueryServiceStatus( hService, &ss ) ) {
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
 
return FALSE;
}
 
if ( ss.dwCurrentState == SERVICE_RUNNING )
break;
 
if ( GetTickCount() - dwStartTime > dwTimeout ) {
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
 
return FALSE;
}
}
 
CloseServiceHandle(hService);
CloseServiceHandle(hSCM);
if (ss.dwCurrentState != SERVICE_RUNNING)
{
return FALSE;
}
 
return TRUE;
}
is it possible to guide me?
QuestionAttachProcessNames() do not show when startedmemberalan9323 Jul '12 - 13:45 
This works fine and starts the program but the program does not show except in the windows processes but I cannot interact with it. Why is this? How can I run the program so I can see it?
QuestionError 87? The parameter is incorrect?memberalan9313 Jul '12 - 9:50 
Do you know what causes that? I have that in my service program on windows 7.
Its an older program but trying to figure out why it does this.
QuestionHigh CPU usage after starting servicememberstanlysamuel27 Jun '12 - 0:56 
When i start service, it is using high CPU. Please help
AnswerRe: High CPU usage after starting servicememberdcube923 Jul '12 - 5:41 
Hi Samuel,
 
I had the same problem and this is my solution :
 
Add Sleep(1); on the end of for() in the function ProcMonitorThread.
 
I hope that is useful also for you.
 
Best regards
Paolo
.: ddd = d3 = dcube :.

QuestionHow could i start windows service as administrator?memberkadvanimayur21 Jun '12 - 20:24 
I am making one application which create socket on particular port and listen all the client and provide them requested system information, for that i need administrator permission.
 
how could i start my windows service with administrator right?
 
By the way your article is awesome. I learned a lot from your article.
QuestionHigh CPU usage after starting servicememberh12126646 Jun '12 - 17:16 
call StartService to run the service result in high CPU usage

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web02 | 2.6.130523.1 | Last Updated 29 Nov 2006
Article Copyright 2006 by Shanmuga Sundar.V
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid