|
下面是我写的一个Service程序框架,实现了如下功能: 1。Service监视窗口的创建。 2。Service中消息处理的实现 3。C++ 类的使用。 4。工作线程函数的使用。 ****如果需要完成特定的工作,只需将线程函数具体化和实例化***。 (程序的注释是用日文写的,因我机器的OS是日文的WIN 2000,VC也是日文的VC6.0不能支持中文,抱歉) /* 日付 バージョン 名前 内容 20040706 1.00 SecBug 新規作成 */ 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.00 SecBug 新規作成 */ //変数宣言 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); }
|