概要
Windows NT/2000/XP系に備わっているWindowsサービスのプロジェクトを作成する方法。
プロジェクト作成
Visual Studioの「ファイル」メニューの「新規作成」にある「プロジェクト」を選択する。 新しいプロジェクトのウインドウが開いたら「Visual C++」ツリーの「ATL」から「ATLプロジ ェクト」を選択し、プロジェクト名を適当に指定して「OK」ボタンを押す。
するとATLプロジェクトウイザードが開く。ここで「次へ」ボタンを押し、画面を「アプリケ ーションの設定」に切り替える。そしてサーバーの種類から「サービス(EXE)」を選び、「完了」 ボタンを押す。
※この手順はVisual Studio 2005 Professional Editionのものだが、他のバージョンでも 同様に操作できる。
自動的に作成されたコード
以上の操作で例えばプロジェクト名が「xxx」の場合は「xxx.cpp」を開くと、次のようなコード が自動的に作成されている。
// xxx.cpp : WinMain の実装 #include "stdafx.h" #include "resource.h" #include "xxx.h" #includeclass CxxxModule : public CAtlServiceModuleT< CxxxModule, IDS_SERVICENAME > { public : DECLARE_LIBID(LIBID_xxxLib) DECLARE_REGISTRY_APPID_RESOURCEID(IDR_XXX, "{8C647C38-27D3-4515-B63A-62E1C648E4B5}") HRESULT InitializeSecurity() throw() { // TODO : CoInitializeSecurity を呼び出し、サービスに適切なセキュリティ設定を // 指定します。 // 推奨 - PKT レベルの認証、 // RPC_C_IMP_LEVEL_IDENTIFY の偽装レベル、 // および適切な NULL 以外のセキュリティ記述子。 return S_OK; } }; CxxxModule _AtlModule; // extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int nShowCmd) { return _AtlModule.WinMain(nShowCmd); }
コードの追加
自動的に作成された、上のコードの中で太字で示したクラスに対し実際にコーディングす るための行を追加し、以下のように変更する。
ここでincludeしているDnpService.hは「Windowsサービスの開始/停止/再起動」 で作成したクラスが定義されているファイルとしている。
// xxx.cpp : WinMain の実装 #include "stdafx.h" #include "resource.h" #include "xxx.h" #include "DnpService.h" #includeclass CxxxModule : public CAtlServiceModuleT< CxxxModule, IDS_SERVICENAME > { public : DECLARE_LIBID(LIBID_xxxLib) DECLARE_REGISTRY_APPID_RESOURCEID(IDR_XXX, "{8C647C38-27D3-4515-B63A-62E1C648E4B5}") HRESULT InitializeSecurity() throw() { // TODO : CoInitializeSecurity を呼び出し、サービスに適切なセキュリティ設定を // 指定します。 // 推奨 - PKT レベルの認証、 // RPC_C_IMP_LEVEL_IDENTIFY の偽装レベル、 // および適切な NULL 以外のセキュリティ記述子。 return S_OK; } // // コマンドラインの追加 // // 以下の3つのコマンドラインオプションを追加する。 // // xxx.exe /Start : サービス開始 // xxx.exe /Stop : サービス停止 // xxx.exe /Restart : サービス再起動 // bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw() { if(!__super::ParseCommandLine(lpCmdLine,pnRetCode)) return false; bool ret; CString strName; CDnpService cService; TCHAR szTokens[] = _T("-/"); *pnRetCode = S_OK; LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); while (lpszToken != NULL) { if(WordCmpI(lpszToken,_T("Start")) == 0) { //サービスの開始 strName.LoadString(IDS_SERVICENAME); ret = cService.EasyStart(strName); *pnRetCode = ret ? S_OK : E_FAIL; return false; } if(WordCmpI(lpszToken,_T("Stop")) == 0) { //サービスの停止 strName.LoadString(IDS_SERVICENAME); ret = cService.EasyStop(strName); *pnRetCode = ret ? S_OK : E_FAIL; return false; } if(WordCmpI(lpszToken,_T("Restart")) == 0) { //サービスの再起動 strName.LoadString(IDS_SERVICENAME); ret = cService.EasyRestart(strName); *pnRetCode = ret ? S_OK : E_FAIL; return false; } lpszToken = FindOneOf(lpszToken, szTokens); } return true; } // // 起動時処理 // HRESULT PreMessageLoop(int nShowCmd) throw() { HRESULT hr = __super::PreMessageLoop(nShowCmd); #if _ATL_VER >= 0x0700 if (SUCCEEDED(hr) && !m_bDelayShutdown) hr = CoResumeClassObjects(); #endif if(SUCCEEDED(hr)) { //TODO:起動時処理をコード } return hr; } // // 終了時処理 // HRESULT PostMessageLoop() { //TODO:終了時処理をコード return __super::PostMessageLoop(); } // // サービス停止処理(SERVICE_CONTROL_STOP) // void OnStop() throw() { //TODO:サービス停止処理をコード __super::OnStop(); } // // サービス一時停止処理(SERVICE_CONTROL_PAUSE) // void OnPause() throw() { //TODO:サービス一時停止処理をコード __super::OnPause(); } // // サービス再開処理(SERVICE_CONTROL_CONTINUE) // void OnContinue() throw() { //TODO:サービス再開処理をコード __super::OnContinue(); } // // サービス問い合わせ処理(SERVICE_CONTROL_INTERROGATE) // void OnInterrogate() throw() { //TODO:サービス問い合わせ処理をコード __super::OnInterrogate(); } // // サービスシャットダウン処理(SERVICE_CONTROL_SHUTDOWN) // void OnShutdown() throw() { //TODO:サービスビスシャットダウン処理をコード __super::OnShutdown(); } // // 不明なサービス処理 // void OnUnknownRequest(DWORD dwOpcode) throw() { //TODO:不明なサービス処理をコード __super::OnUnknownRequest(dwOpcode); } }; CxxxModule _AtlModule; // extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int nShowCmd) { return _AtlModule.WinMain(nShowCmd); }







