わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。

サービス

ログを出力するだけの簡単なサービスです。デバッグログは、DebugViewで確認することができます。 サービスの登録と削除はscコマンドで行います。サービスの開始、終了、一時停止、再開はコントロールパネルのサービスから行えます。

サービスの登録

>sc create TestService binPath= c:\test\TestService.exe displayname= "TestService"
[SC] CreateService SUCCESS

サービスの削除

>sc delete TestService
[SC] CreateService SUCCESS
#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#include <iostream>
#include <windows.h>



/*
	デバッグログの出力
*/
void DebugLog
(
	  LPTSTR szFormat	// フォーマット
	, ...				// パラメータ
)
{
	TCHAR waBuf[ 4096 ] = { 0 };
	va_list args;

	// 可変引数の展開
	va_start( args, szFormat );
	_vsntprintf_s( waBuf, _countof( waBuf ), szFormat, args );
	va_end( args );

	// ログの出力
	::OutputDebugString( waBuf );
}



// サービス名称
#define SERVICE_NAME L"TestService"

// サービスハンドル
SERVICE_STATUS_HANDLE hServiceStatus = NULL; 

// サービス停止中フラグ
BOOL bServiceStop = FALSE;

// 一時停止中フラグ
BOOL bPause = FALSE;



/*
	サービスハンドラ
*/
DWORD WINAPI ServiceHandlerProc
(
	  DWORD dwControl		// 制御コード
	, DWORD dwEventType		// イベントのタイプ
	, LPVOID lpEventData	// イベントのデータ
	, LPVOID lpContext		// Context
)
{
	SERVICE_STATUS tServiceStatus;

	// サービスステータス
	tServiceStatus.dwServiceType             = SERVICE_WIN32_OWN_PROCESS;
	tServiceStatus.dwWin32ExitCode           = NO_ERROR;
	tServiceStatus.dwServiceSpecificExitCode = 0;
	tServiceStatus.dwCheckPoint              = 1;
	tServiceStatus.dwWaitHint                = 3000;
	tServiceStatus.dwControlsAccepted        = SERVICE_ACCEPT_STOP;


	switch( dwControl ) {
	case SERVICE_CONTROL_STOP:
	//----------------------------------
	// サービスの停止					
	//----------------------------------
		{
			DebugLog( L"SERVICE_CONTROL_STOP¥r¥n" );


			/*
				サービスのステータス更新(停止保留中)
			*/
			tServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
			if ( 0 == ::SetServiceStatus ( hServiceStatus, &tServiceStatus ) ) {

				// エラー
				DebugLog( L"SetServiceStatus err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
				break;
			}
			DebugLog ( L"SERVICE_STOP_PENDING¥n" );

			// SERVICE SPECIFIC STOPPING CODE HERE.
			bServiceStop = TRUE;


			// 停止待ち
			Sleep (3 * 1000);


			/*
				サービスのステータス更新(停止)
			*/
			tServiceStatus.dwCurrentState     = SERVICE_STOPPED;
			tServiceStatus.dwCheckPoint       = 0;
			tServiceStatus.dwWaitHint         = 0;
			tServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
			if ( 0 == ::SetServiceStatus( hServiceStatus, &tServiceStatus ) ) {

				// エラー
				DebugLog( L"SetServiceStatus err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
				break;
			}
			DebugLog ( L"SERVICE_STOPPED¥n" );
		}
		break;


	case SERVICE_CONTROL_PAUSE:
	//----------------------------------
	// サービスの一時停止
	//----------------------------------
		{
			DebugLog (TEXT("SERVICE_CONTROL_PAUSE¥n"));


			/*
				サービスのステータス更新(一時停止保留中)
			*/
			tServiceStatus.dwCurrentState = SERVICE_PAUSE_PENDING;
			if ( 0 == SetServiceStatus( hServiceStatus, &tServiceStatus ) ) {

				// エラー
				DebugLog( L"SetServiceStatus err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
				break;
			}
			DebugLog ( L"SERVICE_PAUSE_PENDING¥n" );

			// 一時停止中
			bPause = TRUE;


			/*
				サービスのステータス更新(一時停止)
			*/
			tServiceStatus.dwCurrentState = SERVICE_PAUSED;
			tServiceStatus.dwCheckPoint   = 0;
			tServiceStatus.dwWaitHint     = 0;
			tServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
			if ( 0 == SetServiceStatus( hServiceStatus, &tServiceStatus ) ) {

				// エラー
				DebugLog( L"SetServiceStatus err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
				break; 
			}
			DebugLog ( L"SERVICE_PAUSED¥n" );
		}
		break;


	case SERVICE_CONTROL_CONTINUE:
	//----------------------------------
	// サービスの再開
	//----------------------------------
		{
			DebugLog ( L"SERVICE_CONTROL_CONTINUE¥n" );

			/*
				サービスのステータス更新(再開保留中)
			*/
			tServiceStatus.dwCurrentState = SERVICE_START_PENDING;
			if ( 0 == ::SetServiceStatus( hServiceStatus, &tServiceStatus ) ) {

				// エラー
				DebugLog( L"SetServiceStatus err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
				break;
			}
			DebugLog ( L"SERVICE_START_PENDING¥n" );

			// 実行中
			bPause = FALSE;


			/*
				サービスのステータス更新(再開保留中)
			*/
			// Set RUNNING status.
			tServiceStatus.dwCurrentState     = SERVICE_RUNNING;
			tServiceStatus.dwCheckPoint       = 0;
			tServiceStatus.dwWaitHint         = 0;
			tServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
			if ( 0 == ::SetServiceStatus( hServiceStatus, &tServiceStatus ) ) {

				// エラー
				DebugLog( L"SetServiceStatus err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
				break;
			}
			DebugLog ( L"SERVICE_RUNNING¥n" );
		}
		break;


	default:
		return ERROR_CALL_NOT_IMPLEMENTED;

	}
	return NO_ERROR;
}



/*
	サービスメイン
*/
VOID WINAPI ServiceMain
(
	  DWORD dwArgc
	, PTSTR* pszArgv
)
{
	DebugLog ( L"SERVICE(START)¥n" );

	// サービスハンドラの登録
	hServiceStatus = ::RegisterServiceCtrlHandlerEx(
			  SERVICE_NAME			// サービス名称
			, ServiceHandlerProc	// サービスハンドラ
			, NULL					// Context
		);
	if ( NULL == hServiceStatus ) {

		// エラー
		DebugLog( L"RegisterServiceCtrlHandlerEx err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
		return;
	}


	SERVICE_STATUS tServiceStatus;

	// サービス状態
	tServiceStatus.dwServiceType             = SERVICE_WIN32_OWN_PROCESS;
	tServiceStatus.dwWin32ExitCode           = NO_ERROR;
	tServiceStatus.dwServiceSpecificExitCode = 0;


	/*
		サービスのステータス更新(開始保留中)
	*/
	tServiceStatus.dwCurrentState     = SERVICE_START_PENDING;
	tServiceStatus.dwCheckPoint       = 1;
	tServiceStatus.dwWaitHint         = 1000;
	tServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
	if ( 0 == ::SetServiceStatus ( hServiceStatus, &tServiceStatus ) ) {

		// エラー
		DebugLog( L"SetServiceStatus err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
		return;
	}
	DebugLog ( L"SERVICE_START_PENDING¥n" );


	/*
		サービスのステータス更新(開始)
	*/
	tServiceStatus.dwCurrentState     = SERVICE_RUNNING;
	tServiceStatus.dwCheckPoint       = 0;
	tServiceStatus.dwWaitHint         = 0;
	tServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
	if ( 0 == ::SetServiceStatus ( hServiceStatus, &tServiceStatus ) ) {

		// エラー
		DebugLog( L"SetServiceStatus err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
		return;
	}
	DebugLog ( L"SERVICE_RUNNING¥n" );


	/*
		サービスメイン処理
	*/
	while( !bServiceStop ) {

		// 一時停止中じゃ無ければ実行
		if( !bPause ) {

			// RUNの最中だけ実行
			::OutputDebugString( L"SERVICE(RUN)" );
		 }
		::Sleep( 1000 );
	}

	DebugLog ( L"SERVICE(END)¥n" );
}



/*
	サービス
*/
int _tmain
(
	  int argc
	, _TCHAR* argv[]
)
{
	/*
		サービステーブル
	*/
	static SERVICE_TABLE_ENTRY taServiceTable[] = {
		  { SERVICE_NAME, ServiceMain }
		, { NULL, NULL }
	};


	/*
		サービスプロセスのメインスレッドをサービス制御マネージャに接続し、
		そのスレッドを呼び出し側プロセス用のサービス制御ディスパッチャス
		レッドにする。
	*/
	if ( 0 == ::StartServiceCtrlDispatcher( taServiceTable ) ) {

		// エラー
		DebugLog( L"StartServiceCtrlDispatcher err = 0x%08x¥r¥n", ::HRESULT_FROM_WIN32( ::GetLastError() ) );
		return( -1 );
	}

	// 処理結果を返す
	return( 0 );
}



実行結果

[5592] SERVICE(START)
[5592] SERVICE_START_PENDING
[5592] SERVICE_RUNNING
[5592] SERVICE(RUN)
[5592] SERVICE(RUN)
[5592] SERVICE(RUN)
[5592] SERVICE(RUN)
[5592] SERVICE(RUN)
[5592] SERVICE(RUN)
[5592] SERVICE(RUN)
[5592] SERVICE(RUN)
[5592] SERVICE_CONTROL_STOP 
[5592] SERVICE_STOP_PENDING
[5592] SERVICE(END)
[5592] SERVICE_STOPPED
[7600] SERVICE(START)
[7600] SERVICE_START_PENDING
[7600] SERVICE_RUNNING
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE_CONTROL_PAUSE
[7600] SERVICE_PAUSE_PENDING
[7600] SERVICE_PAUSED
[7600] SERVICE_CONTROL_CONTINUE
[7600] SERVICE_START_PENDING
[7600] SERVICE_RUNNING
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE(RUN)
[7600] SERVICE_CONTROL_STOP 
[7600] SERVICE_STOP_PENDING
[7600] SERVICE(END)






わびさびサンプルソース

WindowsやHTML5などのプログラムのサンプルコードやフリーソフトを提供します。