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