29 August, 2007

Windows Service Simple Sample

Some years ago I was C/C++ developer and I wrote several windows services.
I know that writing of service programs is quite difficult for beginners.

In this post I'm publishing simple working example.
This service only beeps with one second's interval after starts.


service.c

#include <windows.h>

HANDLE hServerStopEvent = NULL;
VOID ServiceBody();
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
VOID WINAPI ServiceControlHandler(DWORD dwCtrlCode);
BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);


SERVICE_STATUS ssStatus;
SERVICE_STATUS_HANDLE sshStatusHandle;

void _cdecl main(int argc, char **argv)
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{{"", (LPSERVICE_MAIN_FUNCTION)ServiceMain }, { NULL, NULL }};
StartServiceCtrlDispatcher(dispatchTable);
}

void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
sshStatusHandle = RegisterServiceCtrlHandler( "", ServiceControlHandler);

if (!sshStatusHandle)
goto cleanup;

ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode = 0;

if (!ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000))
goto cleanup;

ServiceBody();

cleanup:
if (sshStatusHandle)
(VOID)ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 0);
return;
}

VOID WINAPI ServiceControlHandler(DWORD dwCtrlCode)
{
if(dwCtrlCode==SERVICE_CONTROL_STOP)
{
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
if ( hServerStopEvent )
SetEvent(hServerStopEvent);
}
ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
}

BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
if (dwCurrentState == SERVICE_START_PENDING)
ssStatus.dwControlsAccepted = 0;
else
ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

ssStatus.dwCurrentState = dwCurrentState;
ssStatus.dwWin32ExitCode = dwWin32ExitCode;
ssStatus.dwWaitHint = dwWaitHint;

if ( ( dwCurrentState == SERVICE_RUNNING )
|| ( dwCurrentState == SERVICE_STOPPED ) )
ssStatus.dwCheckPoint = 0;
else
ssStatus.dwCheckPoint++;

return SetServiceStatus( sshStatusHandle, &ssStatus);
}


//This sample only beeps.
VOID ServiceBody ()
{
hServerStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!hServerStopEvent)
goto cleanup;

if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
goto cleanup;

do
{
MessageBeep(-1);
} while (WaitForSingleObject(hServerStopEvent, 1000 )== WAIT_TIMEOUT);

cleanup:
if (hServerStopEvent)
CloseHandle(hServerStopEvent);
}



Script for compiling with Visual C++ 6.0:

make_vc6.bat
@call "D:\Program Files\Microsoft Visual Studio\VC98\Bin\vcvars32.bat"
@cl /nologo service.c user32.lib advapi32.lib
@del service.obj

If you use Visual C++ Express, you need additional Platform SDK from Microsoft.

Install (register) service via command:

service_create.bat
sc create "XQX Service" binPath= %CD%\service.exe


Start service via command:

service_start.bat
net start "XQX Service"


Stop service via command:

service_stop.bat
net stop "XQX Service"


Uninstall (remove) service via command:

service_delete.bat
sc delete "XQX Service"

8 comments:

Anonymous said...

I get the error "fatal error C1083: Cannot open include file: 'windows.h': No such file or directory". This is even when I copy windows.h file from it's location in the Platform SDK directory to the directory where I am compiling.

Anonymous said...

you have to install the platform sdk from microsoft _and_ add the include folder and the lib folder to your projects properties...

Unknown said...

Thank you for your good runnable sample code. It works well in my computer. I'm a begineer for service development.

Anonymous said...

Not only that, but it still works in May 2009. Quite an achievement! This is the third example I tried to create a hello world service on Windows XP SP3 and the only one that worked. Not to say that tomorrow or on Vista it probably won't. But let's hope...

ES said...

I was wondering how I can do this for an existing application written in C.

tommy said...

Thank You So Mutch!
This was the first really useful example about services. After spending hours of digging examples witch are doing meny meny meny wonderful things, this was the first that showed: It's after all so simple.

Anonymous said...

Very good, also works on Windows 7 without any changes or problems (of course it doesn't beep as this is no longer possible with Windows 7 / 64bit).

Anonymous said...

I got "fatal error LNK1561: entry point must be defined". wat to do for this? I'm new to C development field. Please help..