ログを出力するだけの簡単なサービスです。デバッグログは、DebugViewで確認することができます。 サービスの登録と削除はscコマンドで行います。サービスの開始、終了、一時停止、再開はコントロールパネルのサービスから行えます。
コマンドラインで/installを指定します。
コマンドラインで/uninstallを指定します。
#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"TestService2" // サービス表示名 #define SERVICE_DISP_NAME L"Test Service2" // サービス詳細 #define SERVICE_DESC_NAME L"テストサービス2" // サービスハンドル 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 InstallService ( ) { // 処理結果 int nRet = 0; // サービスデータベースハンドル SC_HANDLE hSvcDB = NULL; // サービスハンドル SC_HANDLE hService = NULL; /* サービス制御マネージャのデータベースを開く */ hSvcDB = ::OpenSCManager( NULL, NULL, SC_MANAGER_CREATE_SERVICE ); if ( NULL ) { // エラー wprintf( L"OpenSCManager err = 0x%08x", ::HRESULT_FROM_WIN32( ::GetLastError() ) ); nRet = -1; goto err; } // 実行ファイルパスの取得 TCHAR waExePath[ MAX_PATH ]; ::GetModuleFileName( NULL, waExePath, _countof( waExePath ) ); /* サービスの作成 */ hService = ::CreateService( hSvcDB // サービスデータベースハンドル , SERVICE_NAME // サービス名 , SERVICE_DISP_NAME // 表示名 , SERVICE_CHANGE_CONFIG // サービスの構成を変更できるようにする , SERVICE_WIN32_OWN_PROCESS // サービスアプリケーションが専用のプロセス内で動作 , SERVICE_DEMAND_START // StartService関数が呼び出されたときに、サービスが開始される , SERVICE_ERROR_IGNORE // エラー発生時に、サービス開始操作を続行する , waExePath // サービスアプリケーションの実行ファイルパス , NULL , NULL , NULL , NULL , NULL ); if ( NULL == hService ) { // エラー wprintf( L"CreateService err = 0x%08x", ::HRESULT_FROM_WIN32( ::GetLastError() ) ); nRet = -1; goto err; } SERVICE_DESCRIPTION tServiceDescription; // サービス詳細 tServiceDescription.lpDescription = SERVICE_DESC_NAME; // サービスのオプション構成パラメータ変更 if ( 0 == ::ChangeServiceConfig2( hService, SERVICE_CONFIG_DESCRIPTION, &tServiceDescription ) ) { // エラー wprintf( L"ChangeServiceConfig2 err = 0x%08x", ::HRESULT_FROM_WIN32( ::GetLastError() ) ); nRet = -1; goto err; } // インストール成功 std::wcout << L"Service Installed" << std::endl; err: // サービスクローズ if ( NULL != hService ) { ::CloseServiceHandle( hService ); } // データベースクローズ if ( NULL != hSvcDB ) { ::CloseServiceHandle( hSvcDB ); } // 処理結果 return( nRet ); } /* サービスのアンインストール */ int UninstallService ( ) { // 処理結果 int nRet = 0; // サービスデータベースハンドル SC_HANDLE hSvcDB = NULL; // サービスハンドル SC_HANDLE hService = NULL; /* サービス制御マネージャのデータベースを開く */ hSvcDB = ::OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT ); if ( NULL ) { // エラー wprintf( L"OpenSCManager err = 0x%08x", ::HRESULT_FROM_WIN32( ::GetLastError() ) ); nRet = -1; goto err; } // サービスのオープン hService = ::OpenService( hSvcDB, SERVICE_NAME, DELETE ); if ( NULL == hService ) { // エラー wprintf( L"OpenService err = 0x%08x", ::HRESULT_FROM_WIN32( ::GetLastError() ) ); nRet = -1; goto err; } // サービスの削除 if ( 0 == ::DeleteService( hService ) ) { // エラー wprintf( L"DeleteService err = 0x%08x", ::HRESULT_FROM_WIN32( ::GetLastError() ) ); nRet = -1; goto err; } // アンインストール成功 std::wcout << L"Service Uninstalled" << std::endl; err: // サービスクローズ if ( NULL != hService ) { ::CloseServiceHandle( hService ); } // データベースクローズ if ( NULL != hSvcDB ) { ::CloseServiceHandle( hSvcDB ); } // 処理結果 return( nRet ); } /* サービス(登録と削除機能付き) */ int _tmain ( int argc , _TCHAR* argv[] ) { /* コマンドライン引数チェック */ for ( UINT nI = 1; nI < (UINT)__argc; nI++ ) { // サービスのインストール if ( 0 == ::_wcsicmp( L"/install", argv[ nI ] ) ) { return( InstallService() ); } // サービスのアンインストール else if ( 0 == ::_wcsicmp( L"/uninstall", argv[ nI ] ) ) { return( UninstallService() ); } } /* サービステーブル */ 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)