ログを出力するだけの簡単なサービスです。デバッグログは、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)