CServiceApplication
$Revision: 9 $
Description
This class encapsulates the basic logic behind a service application. It
takes care of installing, removing and starting a service as a console
application.
Construction
CServiceApplication( int number_of_command_line_arguments,
LPCTSTR command_line_arguments[],
LPCTSTR service_name,
LPCTSTR friendly_service_name,
LPCTSTR executable_path,
LPTHREAD_START_ROUTINE worker_thread,
SHOW_USAGE_ROUTINE show_usage,
SET_DEFAULTS_ROUTINE set_defaults,
DWORD installation_configuration )-
That's pretty much it.
Data Members
None.
Methods
None.
Example
#include <wfc.h>
#include "messages.h"
#pragma hdrstop
DWORD WINAPI worker_thread( LPVOID pointer_to_parent_CService_class );
VOID set_default_parameters( void );
int __cdecl _tmain( int number_of_command_line_arguments, LPCTSTR command_line_arguments[] )
{
WFCTRACEINIT( TEXT( "_tmain()" ) );
CServiceApplication application( number_of_command_line_arguments,
command_line_arguments,
TEXT( "WatchDog" ),
TEXT( "Service Watch Dog" ),
command_line_arguments[ 0 ],
worker_thread,
NULL,
set_default_parameters );
return( EXIT_SUCCESS );
}
DWORD WINAPI worker_thread( LPVOID )
{
WFCTRACEINIT( TEXT( "worker_thread()" ) );
{
CEventLog log( TEXT( "WatchDog" ) );
log.Report( CEventLog::eventInformation, 0, MSG_WATCHDOG_SERVICE_STARTED );
}
CStringArray names_of_services_to_keep_alive;
DWORD number_of_seconds_to_sleep = 0;
CString machine_name( TEXT( "" ) );
BOOL return_value = TRUE;
{
CRegistry registry;
if ( registry.Connect( CRegistry::keyLocalMachine ) == FALSE )
{
return( 0 );
}
CString key_name( TEXT( "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters" ) );
if ( registry.Open( key_name ) == FALSE )
{
return( 0 );
}
registry.GetValue( TEXT( "Services" ), names_of_services_to_keep_alive );
registry.GetValue( TEXT( "NumberOfSecondsBetweenChecks" ), number_of_seconds_to_sleep );
registry.GetValue( TEXT( "MachineName" ), machine_name );
}
DWORD sleep_time = 1000 * number_of_seconds_to_sleep;
if ( sleep_time < 2000 )
{
// Minimum sleep time is 2 seconds, this give the OS time to do other things
sleep_time = 2000;
}
int number_of_services_to_keep_alive = names_of_services_to_keep_alive.GetSize();
CServiceControlManager service_control_manager;
/*
** Sleep for one minute, this is in case we are starting during boot-up. We want
** to give the service control manager time to start all necessary services before
** we begin restarting stopped services.
*/
Sleep( 60000 );
do
{
if ( machine_name.IsEmpty() )
{
return_value = service_control_manager.Open( GENERIC_READ, NULL, (LPCTSTR *) NULL );
}
else
{
return_value = service_control_manager.Open( GENERIC_READ, NULL, machine_name );
}
if ( return_value != FALSE )
{
if ( service_control_manager.EnumerateStatus( SERVICE_INACTIVE ) != FALSE )
{
CStringArray stopped_services;
CServiceNameAndStatus status;
while( service_control_manager.GetNext( status ) != FALSE )
{
stopped_services.Add( status.lpServiceName );
}
// Now that we have the service names, we need to see which services need to be started
int number_of_stopped_services = stopped_services.GetSize();
int alive_index = 0;
int stopped_index = 0;
while( alive_index < number_of_services_to_keep_alive )
{
stopped_index = 0;
while( stopped_index < number_of_stopped_services )
{
if ( names_of_services_to_keep_alive[ alive_index ].CompareNoCase( stopped_services[ stopped_index ] ) == 0 )
{
// We found one that died, let's start it
service_control_manager.Start( names_of_services_to_keep_alive[ alive_index ] );
// We restarted a service, time to record the event
LPCTSTR string_array[ 1 ];
string_array[ 0 ] = (LPCTSTR) names_of_services_to_keep_alive[ alive_index ];
CEventLog event_log( TEXT( "WatchDog" ) );
event_log.Report( CEventLog::eventInformation,
0,
MSG_WATCHDOG_RESTARTING_SERVICE,
1,
(LPCTSTR *) string_array );
// pop out of the loop
stopped_index = number_of_stopped_services;
}
stopped_index++;
}
alive_index++;
}
}
}
service_control_manager.Close();
Sleep( sleep_time );
}
while( 1 );
return( 0 );
}
void set_default_parameters( void )
{
WFCTRACEINIT( TEXT( "set_default_parameters()" ) );
CRegistry registry;
if ( registry.Connect( CRegistry::keyLocalMachine ) != FALSE )
{
if ( registry.Create( TEXT( "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters" ) ) != FALSE )
{
DWORD default_sleep_time = 60;
if ( registry.SetValue( TEXT( "NumberOfSecondsBetweenChecks" ), default_sleep_time ) == FALSE )
{
LPVOID message_buffer = (LPVOID) NULL;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
registry.GetErrorCode(),
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
(LPTSTR) &message_buffer,
0,
NULL );
LPCTSTR string_array[ 2 ];
string_array[ 0 ] = TEXT( "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters\\NumberOfSecondsBetweenChecks" );
string_array[ 1 ] = (LPCTSTR) message_buffer;
CEventLog event_log( TEXT( "WatchDog" ) );
event_log.Report( CEventLog::eventError,
0,
MSG_CANT_SET_REGISTRY_ENTRY,
2,
(LPCTSTR *) string_array );
if ( message_buffer != NULL )
{
::LocalFree( message_buffer );
}
}
CStringArray strings;
strings.RemoveAll();
strings.Add( TEXT( "" ) );
if ( registry.SetValue( TEXT( "Services" ), strings ) == FALSE )
{
LPVOID message_buffer = (LPVOID) NULL;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
registry.GetErrorCode(),
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
(LPTSTR) &message_buffer,
0,
NULL );
LPCTSTR string_array[ 2 ];
string_array[ 0 ] = TEXT( "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters\\Services" );
string_array[ 1 ] = (LPCTSTR) message_buffer;
CEventLog event_log( TEXT( "WatchDog" ) );
event_log.Report( CEventLog::eventError, 0, MSG_CANT_SET_REGISTRY_ENTRY, 2, (LPCTSTR *) string_array );
if ( message_buffer != NULL )
{
::LocalFree( message_buffer );
}
}
}
else
{
LPVOID message_buffer = (LPVOID) NULL;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
registry.GetErrorCode(),
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
(LPTSTR) &message_buffer,
0,
NULL );
LPCTSTR string_array[ 2 ];
string_array[ 0 ] = TEXT( "SYSTEM\\CurrentControlSet\\Services\\WatchDog\\Parameters" );
string_array[ 1 ] = (LPCTSTR) message_buffer;
CEventLog event_log( "WatchDog" );
event_log.Report( CEventLog::eventError, 0, MSG_CANT_CREATE_REGISTRY_KEY, 2, (LPCTSTR *) string_array );
if ( message_buffer != NULL )
{
::LocalFree( message_buffer );
}
}
}
else
{
LPVOID message_buffer = (LPVOID) NULL;
::FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
registry.GetErrorCode(),
MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ),
(LPTSTR) &message_buffer,
0,
NULL );
LPCTSTR string_array[ 2 ];
string_array[ 0 ] = TEXT( "keyLocalMachine" );
string_array[ 1 ] = (LPCTSTR) message_buffer;
CEventLog event_log( TEXT( "WatchDog" ) );
event_log.Report( CEventLog::eventError, 0, MSG_CANT_CONNECT_TO_REGISTRY, 2, (LPCTSTR *) string_array );
if ( message_buffer != NULL )
{
::LocalFree( message_buffer );
}
}
}
Copyright, 2000, Samuel R. Blackburn
$Workfile: CServiceApplication.cpp $
$Modtime: 6/26/01 10:51a $