下面是我写的一个Service程序框架,实现了如下功能:
1。Service监视窗口的创建。
2。Service中消息处理的实现
3。C++ 类的使用。
4。工作线程函数的使用。
****如果需要完成特定的工作,只需将线程函数具体化和实例化***。
(程序的注释是用日文写的,因我机器的OS是日文的WIN 2000,VC也是日文的VC6.0不能支持中文,抱歉)
/*
日付 バージョン名前内容
20040706 1.00SecBug 新規作成
*/
class MyServiceModel
{
public:
MyServiceModel();
virtual ~MyServiceModel();
private:
//変数
// サービス名
LPCTSTR serviceName;
//サービスの状態を保持する
SERVICE_STATUS serviceStatus;
// private サービスのハンドル
SERVICE_STATUS_HANDLE serviceStatusHandle;
HWND hCMain_seivice_data;
//---------------私-----------
// Event used to hold ServiceMain from completing
HANDLE terminateEvent;
// Thread for the actual work
HANDLE threadHandle;
// Flags holding current state of service
BOOL pauseService ;
BOOL runningService ;
//メソッド
public:
//メインメソッド:
int main(int argc, TCHAR* argv[]);
//サービスインストール:
void InstallService();
// サービスアンインストール:
void UninstallService();
//サービスメイン:
void WINAPI ServiceMain(DWORD argc, TCHAR* argv[]);
//サービスコントロールハンドラー:
void WINAPI ServiceControlHandler(DWORD contorlCode );
//ウインドウプロシージャ:
LRESULT CALLBACK WndProc(HWND hDlg, UINT Msg, WPARAM wParam ,LPARAM lParam);
//---------------私-----------
//ウインドウプロシージャ
static LRESULT CALLBACK _WndProc(
HWND hDlg,
UINT Msg,
WPARAM wParam ,
LPARAM lParam
);
//サービスコントロールハンドラー
static void WINAPI _ServiceControlHandler(DWORD contorlCode );
//サービスメイン
static void WINAPI _ServiceMain( DWORD argc, TCHAR * argv[] );
BOOL CreateSvcWindow();
//エラー 処理
void ErrorHandler(char *s, DWORD err);
//サービス終了する
VOID terminate(DWORD error);
//ステータス報告する
BOOL SendStatusToSCM (
DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwServiceSpecificExitCode,
DWORD dwCheckPoint,
DWORD dwWaitHint
);
//サービス終了
VOID StopService();
//初期化サービス
BOOL InitService();
//レジメサービス
VOID ResumeService();
//ポーズサービス
VOID PauseService();
//
BOOL RunService(char *sSvcName);
};
//スレッド関数
DWORD WINAPI ServiceThread(LPDWORD param);
/*
日付 バージョン名前内容
20040706 1.00SecBug 新規作成
*/
//変数宣言
extern MyServiceModel objApp;
//////////////////////////////////////////////////////////////////////
// 構築/消滅
//////////////////////////////////////////////////////////////////////
/*
機能 構築
static
可視性 public
メソッド名 MyServiceModel
引数
なし
戻り値
なし
*/
MyServiceModel::MyServiceModel()
{
// サービス名
serviceName = "MyServiceName";
//サービスの状態を保持する
serviceStatusHandle = NULL;
}
/*
機能 消滅
static
可視性 public
メソッド名 ~MyServiceModel
引数
なし
戻り値
なし
*/
MyServiceModel::~MyServiceModel()
{
}
/*
機能メインメソッド
static
可視性 public
メソッド名 main
引数
引数の数 [IN] argc int 初期値なし
各引数 [IN] argv TCHAR *[] 初期値なし
戻り値
int 常に0
備考
なし
*/
int MyServiceModel::main(int argc, TCHAR * argv[])
{
int iRet = 0;
TCHAR TServceName[256];
strcpy(TServceName,SVCSTARTNAME);
SERVICE_TABLE_ENTRY dispatchTable[]=
{
{TEXT(TServceName),(LPSERVICE_MAIN_FUNCTION)_ServiceMain},
{ NULL,NULL}
};
//引数のチェック:
if(argc<=1)
{
//ブランクの場合は、usage(使用方法)表示
cout<<"usage :"<<ENDL;
//cout<<"zxz\"zxz"<<ENDL;
//"install"
cout<<"\"install\"";
//"or"
cout<<"or";
//"uninstall"
cout<<"\"uninstall\"";
//"exec"
cout<<"\"exec \"";
cout<<" parameter required in the command line"<<ENDL;??
}
//installの場合、サービスの登録を行う(InstallService呼出)
if(argc>1)
{
if(_stricmp("install",argv[1])==0)
{
InstallService();
}
//uninstallの場合、サービスの削除を行う(UninstallService呼出)
else if(_stricmp("uninstall",argv[1])==0)
{
UninstallService();
}
//execの場合、サービスの起動を行う(ServiceMain呼出)
else if(_stricmp("exec",argv[1])==0)
{
RunService(SVCSTARTNAME);
}
//ブランクの場合は、usage(使用方法)表示
else
{
cout<<"usage :"<<ENDL;
//"install"
cout<<"\"install\"";
//"or"
cout<<"or";
//"uninstall"
cout<<"\"uninstall\"";
//"exec"
cout<<"\"exec \"";
//"or"
cout<<"or";
cout<<" parameter required in the command line"<<ENDL;
}
}
//ブランクの場合、サービスの起動を行う(RunService呼出)
else
{
//RunService呼出
BOOL success;
success = StartServiceCtrlDispatcher(dispatchTable);
if(success)
{
ErrorHandler("In StartServiceCtrlDispatcher",GetLastError());
}
}
//戻り値 常に0
iRet = 0;
return iRet;
}
/*
機能 サービスインストール
static
可視性 public
メソッド名 InstallService
引数
なし
戻り値
なし
備考
サービスのインストールを行う
*/
void MyServiceModel::InstallService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
TCHAR szPath[512];
cout<<"Install Starting..."<<ENDL;
//ファイルパースお獲得する
if(!GetModuleFileName(NULL,szPath,512))
{
ErrorHandler("In GetModuleFileName",GetLastError());
return;
}
// openコネクション to SCM
schSCManager = OpenSCManager(
0, // pointer to machine name string
0, // pointer to database name string
SC_MANAGER_CREATE_SERVICE // type of access
);
if (!schSCManager)
{
ErrorHandler("In OpenScManager",GetLastError());
return;
}
// Install 新サービス
schService = CreateService(
schSCManager, // handle to service control manager database
SVCSTARTNAME, // pointer to name of service to start
SVCDISPLNAME, // pointer to display name
SERVICE_ALL_ACCESS,// type of access to service
SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS ,// type of service
SERVICE_DEMAND_START,// when to start service
SERVICE_ERROR_NORMAL,// severity if service fails to start
szPath, // pointer to name of binary file
NULL, // pointer to name of load ordering group
NULL, // pointer to variable to get tag identifier
NULL, // pointer to array of dependency names
NULL, // pointer to account name of service
NULL // pointer to password for service account
);
if (!schService)
{
ErrorHandler("In CreateService",GetLastError());
return;
}
else
{
cout << "Service installed\n";
}
// clean up
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
cout << "Install Ending...\n";
}
/*
機能 サービスのアンインストール
static
可視性 public
メソッド名 UninstallService
引数
なし
戻り値
なし
備考
サービスのアンインストールを行う
*/
void MyServiceModel::UninstallService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;
BOOL success;
SERVICE_STATUS svcStatus;
cout << "Uninstall Starting..."<<ENDL;?
// openコネクション to SCM
schSCManager = OpenSCManager(
0,// pointer to machine name string
0,// pointer to database name string
SC_MANAGER_CREATE_SERVICE // type of access
);
if (!schSCManager)
{
ErrorHandler("In OpenScManager",GetLastError());
return;
}
// サービスハンドル獲得する
schService = OpenService(
schSCManager, // handle to service control manager database
SVCSTARTNAME, // pointer to name of service to start
SERVICE_ALL_ACCESS | DELETE// type of access to service
);
if (!schService)
{
ErrorHandler("In OpenService",GetLastError());
return;
}
// サービス終了 (if necessary)
success = QueryServiceStatus(schService, &svcStatus);
if (!success)
{
ErrorHandler("In QueryServiceStatus",GetLastError());
return;
}
if (svcStatus.dwCurrentState != SERVICE_STOPPED)
{
cout << "Stopping service..."<<ENDL;
success = ControlService(
schService, // handle to service
SERVICE_CONTROL_STOP, // control code
&svcStatus // pointer to service status structure
);
if (!success)
{
ErrorHandler("In ControlService",GetLastError());
return;
}
}
//サービス終了待つこと
do
{
QueryServiceStatus(schService,&svcStatus);
Sleep(500);
}while(SERVICE_STOP_PENDING==svcStatus.dwCurrentState);
if(SERVICE_STOPPED!=svcStatus.dwCurrentState)
{
ErrorHandler("Failed to Stop Service",GetLastError());
return;
}
// サービス削除する
success = DeleteService(schService);
if (success)
{
cout << "Service removed\n";
}
else
{
ErrorHandler("In DeleteService",GetLastError());
return;
}
// サービスClean up
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
cout << "Uninstal Ending..."<<ENDL;?
}
/*
機能 サービスメイン
static
可視性 public
メソッド名 ServiceMain
引数
引数の個数 [IN] argc DWORD なし
各引数 [IN] argv TCHAR *[] なし
戻り値
なし
備考
コントロール パネルのサービス アプリケーションを開いて、サービスを選択して [開始] をクリックした際に、SCMから呼び出される。
サービスのメイン処理を行う:
*/
void WINAPI MyServiceModel::ServiceMain(DWORD argc,TCHAR *argv[])
{
BOOL success;
// SCM にハンドラ関数を渡す
serviceStatusHandle = RegisterServiceCtrlHandler(
SVCSTARTNAME,
(LPHANDLER_FUNCTION)_ServiceControlHandler
);
if (! serviceStatusHandle)
{
terminate(GetLastError());
return;
}
// サービスを開始状態にする
success = SendStatusToSCM(
SERVICE_START_PENDING,
NO_ERROR,
0,
1,
5000
);
if (!success)
{
terminate(GetLastError());
return;
}
// 終了イベント創造する
terminateEvent = CreateEvent (
0,
TRUE,
FALSE,
0
);
if (! terminateEvent)
{
terminate(GetLastError());
return;
}
// SCM 通報する
success = SendStatusToSCM(
SERVICE_START_PENDING,
NO_ERROR,
0,
2,
1000
);
if (!success)
{
terminate(GetLastError());
return;
}
// 初期化サービス,
//メッセージIDを取得して、変数お代入
//ウインドウの作成
success = InitService();
if (!success)
{
terminate(GetLastError());
return;
}
// サービス 実行.
//SCM 通報する
success = SendStatusToSCM(
SERVICE_RUNNING,
NO_ERROR,
0,
0,
0
);
if (!success)
{
terminate(GetLastError());
return;
}
// サービスの停止待ち
WaitForSingleObject ( terminateEvent, INFINITE);
//サービスを停止状態にする。
terminate(0);
}
/*
機能 サービスコントロールハンドラー
static
可視性 public
メソッド名 ServiceControlHandler
引数
状態コード [IN] contorlCode DWORD なし
戻り値
なし
備考
"SCM がサービスのステータスを得たり、停止や一時停止などの各種の命令をサービスに送るためにSCMから呼び出される。
SCM は Handler に、実行すべき処理の種類を表す処理コードを渡します。
1. サービス停止通知が来た場合、サービス停止中に変更
2. 停止処理を行う(ServiceMainに停止を通知)
3. その他の場合は何もしない
*/
void WINAPI MyServiceModel::ServiceControlHandler(DWORD contorlCode )
{
DWORD currentState = 0;
BOOL success;
switch(contorlCode)
{
// There is no START option because
// ServiceMain gets called on a start
// サービス終了する
case SERVICE_CONTROL_STOP:
currentState = SERVICE_STOP_PENDING;
// Tell the SCM what's happening
success = SendStatusToSCM(
SERVICE_STOP_PENDING,
NO_ERROR,
0,
1,
5000
);
// Not much to do if not successful
// Stop the service
StopService();
return;
// サービスポーズ
case SERVICE_CONTROL_PAUSE:
if ( runningService && ! pauseService)
{
// Tell the SCM what's happening
success = SendStatusToSCM(
SERVICE_PAUSE_PENDING,
NO_ERROR,
0,
1,
1000);
PauseService();
currentState = SERVICE_PAUSED;
}
break;
//サービス再び始める
case SERVICE_CONTROL_CONTINUE:
if ( runningService && pauseService)
{
// Tell the SCM what's happening
success = SendStatusToSCM(
SERVICE_CONTINUE_PENDING,
NO_ERROR,
0,
1,
1000
);
ResumeService();
currentState = SERVICE_RUNNING;
}
break;
// サービスの現在のステータス更新
case SERVICE_CONTROL_INTERROGATE:
// it will fall to bottom and send status
break;
// Do nothing in a shutdown. Could do cleanup
// here but it must be very quick.
case SERVICE_CONTROL_SHUTDOWN:
// Do nothing on shutdown
return;
default:
break;
}
//サービスの現在のステータス更新
SendStatusToSCM(
currentState,
NO_ERROR,
0,
0,
0
);
}
/*
機能 ウインドウプロシージャ
static
可視性 public
メソッド名 WndProc
引数
ウインドウハンドル [IN] hDlg HWND なし
メッセージ [IN] Msg UINT なし
パラメタ1 [IN] wParam WPARAM なし
パラメタ2 [IN] lParam LPARAM なし
戻り値
LRESULT
備考
"ウインドウメッセージの解析処理を行う
*/
LRESULT CALLBACK MyServiceModel::WndProc(HWND hDlg, UINT Msg, WPARAM wParam ,LPARAM lParam)
{LRESULT lrRet;
/*
//test begin
HDC hdc;
PAINTSTRUCT ps;
int x,y;
x = 60;
y = 20;
test end
*/
switch(Msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
};
//その他のメッセージの場合は、DefWindowProcを呼出"
lrRet = DefWindowProc(hDlg,Msg,wParam,lParam);
return lrRet;
}
/*
機能 エラー 処理
static
可視性 private
メソッド名 ErrorHandler
引数
パラメタ1 [IN] char *s なし
パラメタ2 [IN] DWORD err なし
戻り値
なし
備考
なし
*/
void MyServiceModel::ErrorHandler(char *s, DWORD err)
{
cout <<S<<ENDL;
cout << "Error number: " << err << endl;
char str1[50];
char str2[20];
memset(str1,0,sizeof(str1));
memset(str2,0,sizeof(str2));
strcpy(str1,s);
strcat(str1,", Error Code: ");
itoa(err,str2,10);
strcat(str1,str2);
ExitProcess(err);
}
/*
機能 サービス終了する
static
可視性 private
メソッド名 terminate
引数
パラメタ DWORD error なし
戻り値
なし
備考
サービス終了する
*/
VOID MyServiceModel::terminate(DWORD error)
{
// if terminateEvent has been created, close it.
if (terminateEvent)
CloseHandle(terminateEvent);
// Send a message to the scm to tell about
// stopage
if (serviceStatusHandle)
SendStatusToSCM(SERVICE_STOPPED, error,
0, 0, 0);
// If the thread has started kill it off
if (threadHandle)
CloseHandle(threadHandle);
// Do not need to close serviceStatusHandle
}
/*
機能 ステータス報告する
static
可視性 private
メソッド名
引数
パラメタ1 DWORD dwCurrentState,
パラメタ2 DWORD dwWin32ExitCode,
パラメタ3 DWORD dwServiceSpecificExitCode,
パラメタ4 DWORD dwCheckPoint,
パラメタ5 DWORD dwWaitHint
戻り値
なし
備考
consolidates the activities of updating the service status with SetServiceStatus
*/
BOOL MyServiceModel::SendStatusToSCM (DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwServiceSpecificExitCode,
DWORD dwCheckPoint,
DWORD dwWaitHint)
{
BOOL success;
SERVICE_STATUS serviceStatus;
// Fill in all of the SERVICE_STATUS fields
serviceStatus.dwServiceType =
SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwCurrentState = dwCurrentState;
// If in the process of something, then accept
// no control events, else accept anything
if (dwCurrentState == SERVICE_START_PENDING)
serviceStatus.dwControlsAccepted = 0;
else
serviceStatus.dwControlsAccepted =
SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE |
SERVICE_ACCEPT_SHUTDOWN;
// if a specific exit code is defines, set up
// the win32 exit code properly
if (dwServiceSpecificExitCode == 0)
serviceStatus.dwWin32ExitCode =
dwWin32ExitCode;
else
serviceStatus.dwWin32ExitCode =
ERROR_SERVICE_SPECIFIC_ERROR;
serviceStatus.dwServiceSpecificExitCode =
dwServiceSpecificExitCode;
serviceStatus.dwCheckPoint = dwCheckPoint;
serviceStatus.dwWaitHint = dwWaitHint;
// Pass the status record to the SCM
success = SetServiceStatus (serviceStatusHandle,
&serviceStatus);
if (!success)
StopService();
return success;
}
/*
機能 初期化サービス
static
可視性 private
メソッド名 InitService
引数
なし
戻り値
なし
備考
Initializes the service by starting its thread
*/
BOOL MyServiceModel::InitService()
{
DWORD id;
// Start the service's thread
threadHandle = CreateThread(0, 0,
(LPTHREAD_START_ROUTINE) ServiceThread,
0, 0, &id);
if (threadHandle==0)
return FALSE;
else
{
runningService = TRUE;
return TRUE;
}
}
/*
機能 Startサービス
static
可視性 private
メソッド名 StartService
引数
sSvcName :サービス名
戻り値
なし
備考
Resumes a paused service
*/
BOOL MyServiceModel::RunService(char *sSvcName)
{
SC_HANDLE schSCManager;
SC_HANDLE scHandle;
BOOL boolRet;
// openコネクション to SCM
schSCManager = OpenSCManager(
0,
0,
SC_MANAGER_ALL_ACCESS
);
//Open サービス
scHandle = OpenService(
schSCManager,
sSvcName,
SERVICE_ALL_ACCESS
);
//start サービス
boolRet = StartService(
scHandle,
0,
NULL);
return boolRet;
}
/*
機能 レジメサービス
static
可視性 private
メソッド名 ResumeService
引数
なし
戻り値
なし
備考
Resumes a paused service
*/
VOID MyServiceModel::ResumeService()
{
//pauseService=FALSE;
//ResumeThread(threadHandle);
return;
}
/*
機能ポーズサービス
static
可視性 private
メソッド名 PauseService
引数
なし
戻り値
なし
備考
Pauses the service
*/
VOID MyServiceModel::PauseService()
{
//pauseService = TRUE;
//SuspendThread(threadHandle);
return;
}
/*
機能 サービス終了
static
可視性 private
メソッド名
引数
パラメタ なし
戻り値
なし
備考
Stops the service by allowing ServiceMain to complete
*/
VOID MyServiceModel::StopService()
{
runningService=FALSE;
// Set the event that is holding ServiceMain
// so that ServiceMain can return
SetEvent(terminateEvent);
}
/*
機能 スレッド関数
static
可視性 private
メソッド名 ServiceThread
引数
パラメタLPDWORD param
戻り値
0
備考
なし
*/
DWORD WINAPI ServiceThread(LPDWORD param)
{
//ウインドウの作成
objApp.CreateSvcWindow();
return 0;
}
/*
機能 ウインドウの作成
static
可視性 private
メソッド名 CreateSvcWindow
引数
パラメタ なし
戻り値
なし
備考
なし
*/
BOOL MyServiceModel:: CreateSvcWindow()
{
//ウインドウの作成
//the handle of the windows
HWND hwnd;
//the struct of the WNDCALSS
WNDCLASS wc;
MSG msg;
HINSTANCE hInstance=(HINSTANCE)::GetModuleHandle(NULL);
wc.style = CS_VREDRAW|CS_HREDRAW;
wc.lpfnWndProc = (WNDPROC)(_WndProc);
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance,IDI_APPLICATION);
wc.hCursor =LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "PDFMainSvcWindow";
//register the windows class
ATOM aaa = RegisterClass(&wc);
if(aaa == 0)
{
cout<<" RegisterClass Error:"<<GETLASTERROR()<<ENDL;
}
//ウインドウの作成
hwnd = CreateWindow(
"PDFMainSvcWindow",
"メインサービスウインドウ",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT ,
CW_USEDEFAULT ,
CW_USEDEFAULT ,
CW_USEDEFAULT ,
NULL,
NULL,
hInstance,
NULL
);
if(!hwnd)
return FALSE;
ShowWindow(hwnd,SW_SHOWNORMAL);
UpdateWindow(hwnd);
hCMain_seivice_data = hwnd;
//最初回のタイマーを設定する。
SetTimer(hwnd,TIMER_SYS_ID,TIMER_ELAPSE_VALUE,NULL);
//メッセージループの開始
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//while(1){};
return FALSE;
}
/*
機能 サービスメイン
static
可視性 public
メソッド名 ServiceMain
引数
引数の個数 [IN] argc DWORD なし
各引数 [IN] argv TCHAR *[] なし
戻り値
なし
備考
コントロール パネルのサービス アプリケーションを開いて、サービスを選択して [開始] をクリックした際に、SCMから呼び出される。
サービスのメイン処理を行う:
*/
void WINAPI MyServiceModel::_ServiceMain(DWORD argc, TCHAR *argv[])
{
objApp.ServiceMain(argc,argv);
}
/*
機能 サービスコントロールハンドラー
static
可視性 public
メソッド名 ServiceControlHandler
引数
状態コード [IN] contorlCode DWORD なし
戻り値
なし
備考
"SCM がサービスのステータスを得たり、停止や一時停止などの各種の命令をサービスに送るためにSCMから呼び出される。
SCM は Handler に、実行すべき処理の種類を表す処理コードを渡します。
1. サービス停止通知が来た場合、サービス停止中に変更
2. 停止処理を行う(ServiceMainに停止を通知)
3. その他の場合は何もしない"
*/
void WINAPI MyServiceModel::_ServiceControlHandler(DWORD contorlCode)
{
objApp.ServiceControlHandler(contorlCode);
}
/*
機能 ウインドウプロシージャ
static
可視性 public
メソッド名 WndProc
引数
ウインドウハンドル [IN] hDlg HWND なし
メッセージ [IN] Msg UINT なし
パラメタ1 [IN] wParam WPARAM なし
パラメタ2 [IN] lParam LPARAM なし
戻り値
LRESULT
備考
"ウインドウメッセージの解析処理を行う
*/
LRESULT CALLBACK MyServiceModel::_WndProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
{
return objApp.WndProc(hDlg,Msg,wParam,lParam);
}