伴隨著研究Windows服務,逐漸掌握了一些小技巧,現在與大家分享一下。
將Windows服務轉變為控制台程式
由於預設的Windows服務程式,編譯後為Win32的視窗程序。我們在程式啟動或運行過程中,如果想看到一些調試資訊,那麼就只能通過DebugView或者輸出到日誌的方式了。因為如果我們通過printf或者std::cout輸出調試資訊的話,Win32視窗程序是無法顯示的。
此時,我們是多麼懷念我們的經典的控制台程式啊,它可以很方便的將我們的調試資訊輸出出來,簡直是太方便了。既然如此,那我們就讓它一秒鐘變格格吧,額,應該是一秒鐘變控制台。
下面分享一下我的實現代碼
Collapse#ifdef _DEBUG//Debug版本,直接輸出到控制台#define OUT(s) printf_s(s); #define OUT_LN(s) printf_s(s##"\r\n"); #else//非Debug版本,則輸出到調試器,一般使用DebugView#define OUT(s) OutputDebugString(s);#define OUT_LN(s) OutputDebugString(s);#endif class CServicesModule : public ATL::CAtlServiceModuleT< CServicesModule, IDS_SERVICENAME >{public : DECLARE_LIBID(LIBID_ServicesLib) DECLARE_REGISTRY_APPID_RESOURCEID(IDR_SERVICES, "{0794CF96-5CC5-432E-8C1D-52B980ACBE0F}") HRESULT InitializeSecurity() throw() { return S_OK; } //服務啟動 HRESULT Load(); //服務停止 HRESULT UnLoad(); HRESULT Run(_In_ int nShowCmd = SW_HIDE) throw() { HRESULT hr = S_OK; OUT_LN("準備啟動服務"); hr = Load(); if(hr) { OUT_LN("啟動服務失敗"); return hr; } OUT_LN("Services服務已啟動"); hr = ATL::CAtlServiceModuleT< CServicesModule, IDS_SERVICENAME >::Run(nShowCmd); hr = UnLoad(); OUT_LN("Services服務正常退出"); return hr; }}; CServicesModule _AtlModule; //#ifndef _DEBUG//非Debug版本,編譯為Win32程式extern "C" int WINAPI _tWinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int nShowCmd){ return _AtlModule.WinMain(nShowCmd);}#else//Debug版本,編譯為控制台程式int _tmain(int argc, _TCHAR* argv[]){ return _AtlModule.WinMain(SW_SHOW);}#endif HRESULT CServicesModule::Load(){ OUT_LN("服務正在啟動"); return 0;} HRESULT CServicesModule::UnLoad(){ OUT_LN("服務正在停止"); return 0;}
通過_DEBUG宏來區分是否編譯成控制台程式。
當指定編譯Debug版本時,可以將程式編譯為控制台程式,通過RegServer註冊服務,然後直接運行服務exe程式,這樣通過printf輸出的資訊,就可以在控制台上顯示了,如下圖。
當指定編譯Release版本時,將程式編譯為Win32程式,通過Service註冊服務,通過服務管理員管理服務的運行和停止。