Windows NTService 后台框架封装
对于后台运行的程序,比如基于C/S架构的服务器、各种监控系统的程序、或者是程序额外的功能需要后台运行来实现,在Windows平台中,服务经常会用到,这种对于需要24×7运行的程序是必备的,至少本人经常需要运用windows服务来搭建后台程序。于是查阅网上的各种资料,发现有不少的参考实例,但是使用起来有各种问题,不少是这些作者或者使用者对Windows NT Service API接口运用的不熟练或者不清楚,导致自己花费很多时间在理解这些错误的实例当中,不过折腾到最后,还是从错误中得到不少教训的。所以为了方便以后能够直接使用,不再做重复的工作,便在工作之余将Windows NT Service API接口进行了二次封装并简单的测试通过,发上来也让大家使用并指正其中的错误。
当然,有更权威的参考实例。http://msdn.microsoft.com/en-us/library/windows/desktop/bb540476(v=vs.85).aspx
废话不多说, 先直接贴上代码,希望不要被贱笑了...
NTService.h
#ifndef _NTSERVICE_H_
#define _NTSERVICE_H_ ///服务启动类型定义
enum SERVICE_STARTUP_TYPE
{
//禁用不可启动
SST_DISABLED=, //随系统启动自动启动
SST_AUTO_START=, //命令/手动启动
SST_DEMAND_START=
}; ///服务执行的任务对象
class ServiceTask
{
public:
ServiceTask(){}
virtual ~ServiceTask(){} public:
///服务初始化通知
///@return 成功返回0, 否则-1
///@remark 完成后需及时返回, 不能长时间阻塞
virtual int OnInit(int argc, char **argv){return ;} ///服务启动通知
///@remark 服务启动阻塞执行此过程, 直至服务停止/关闭
virtual void OnStart(){} ///服务停止通知
///@remark OnStart结束返回, 服务变为停止状态
virtual void OnStop(){} ///服务暂停通知
///@remark OnStart暂停执行, 服务变为暂停状态
virtual void OnPause(){} ///被暂停的服务恢复通知
///@remark OnStart恢复执行, 服务变为恢复状态
virtual void OnContinue(){} ///服务被强制关闭通知
///@remark 通常是OS关闭时发生
virtual void OnShutdown(){}
}; class NTServiceImpl; ///服务接口控制对象
class NTService
{
public:
///@param name服务名称
///@param canstop是否可停止
///@param canshutdown是否可关闭
///@param canpausecontinue是否可暂停继续
NTService(const char *name,
bool canstop=true,
bool canshutdown=true,
bool canpausecontinue=false); ~NTService(); public:
///检查服务是否安装
bool IsInstalled(); ///安装服务
///@param display_name服务显示的名称
///@param type服务启动类型
///@return 成功返回0, 否则-1
int Install(const char *display_name, SERVICE_STARTUP_TYPE type); ///卸载服务
///@return 成功返回0, 否则-1
int UnInstall(); ///设置服务启动类型
///@return 成功返回0, 否则-1
int SetStartupType(SERVICE_STARTUP_TYPE type); ///更新服务描述信息
///@return 成功返回0, 否则-1
int UpdateDesc(const char *desc); ///启动服务
///@return 成功返回0, 否则-1
///@param argc启动参数个数
///@param argv启动参数列表
int Start(int argc=, const char **argv=); ///停止服务
///@return 成功返回0, 否则-1
int Stop(); ///获取服务当前状态
///@return 成功返回状态值, 否则-1
int GetCurrentStatus(); public:
///系统启动服务调用
///@remark 不可主动调用
int Run(ServiceTask &service); private:
NTServiceImpl *m_impl;
}; #endif//_NTSERVICE_H_
NTServiceImpl.h
#ifndef _NTSERVICE_IMPL_H_
#define _NTSERVICE_IMPL_H_
#include "NTService.h"
#include <Windows.h>
#include <string> class NTServiceImpl
{
public:
NTServiceImpl(const char *name,
bool canstop,
bool canshutdown,
bool canpausecontinue); ~NTServiceImpl(); public:
bool IsInstalled();
int Install(const char *display_name, SERVICE_STARTUP_TYPE type);
int UnInstall();
int SetStartupType(SERVICE_STARTUP_TYPE type);
int UpdateDesc(const char *desc);
int Start(int argc, const char **argv);
int Stop();
int GetCurrentStatus(); int Run(ServiceTask &service); private:
std::string m_name;
bool m_canstop;
bool m_canshutdown;
bool m_canpausecontinue;
}; class NTServiceManager
{
private:
NTServiceManager();
~NTServiceManager(); public:
static bool IsInstalled(const char *name);
static int Install(const char *name, const char *display_name, SERVICE_STARTUP_TYPE type);
static int UnInstall(const char *name);
static int SetStartupType(const char *name, SERVICE_STARTUP_TYPE type);
static int UpdateDesc(const char *name, const char *desc);
static int Start(const char *name, int argc, const char **argv);
static int Stop(const char *name);
static int GetCurrentStatus(const char *name); private:
static int GetRealStartupType(SERVICE_STARTUP_TYPE type);
}; class NTServiceHandler
{
private:
NTServiceHandler(const std::string &name,
bool canstop,
bool canshutdown,
bool canpausecontinue,
ServiceTask &service); ~NTServiceHandler(); public:
static void CreateInstance(const std::string &name,
bool canstop,
bool canshutdown,
bool canpausecontinue,
ServiceTask &service)
{
DestroyInstance();
m_this =new NTServiceHandler(name, canstop, canshutdown, canpausecontinue, service);
}
static NTServiceHandler *GetInstance()
{
return m_this;
}
static void DestroyInstance()
{
if (m_this)
{
delete m_this;
m_this = ;
}
} public:
int Run(); private:
static void ServiceMainHandler(DWORD argc, LPSTR *argv);
static void ServiceCtrlHandler(DWORD ctrl); private:
void NTS_Start(DWORD argc, LPSTR *argv);
void NTS_Stop();
void NTS_Pause();
void NTS_Continue();
void NTS_Shutdown(); void SetServiceStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode=NO_ERROR,
DWORD dwWaitHint=); int OnInit(int argc, char **argv);
void OnStart();
void OnStop();
void OnPause();
void OnContinue();
void OnShutdown(); private:
std::string m_name;
ServiceTask &m_service; SERVICE_STATUS m_status;
SERVICE_STATUS_HANDLE m_status_handle; static NTServiceHandler *m_this;
}; NTServiceHandler *NTServiceHandler::m_this = ; #endif//_NTSERVICE_IMPL_H_
NTServiceImpl.cpp
#include "NTServiceImpl.h"
#include <assert.h> NTService::NTService(const char *name,
bool canstop,
bool canshutdown,
bool canpausecontinue)
{
m_impl = new NTServiceImpl(name, canstop, canshutdown, canpausecontinue);
}
NTService::~NTService()
{
if (m_impl)
{
delete m_impl;
m_impl = ;
}
}
bool NTService::IsInstalled()
{
return m_impl->IsInstalled();
}
int NTService::Install(const char *display_name, SERVICE_STARTUP_TYPE type)
{
return m_impl->Install(display_name, type);
}
int NTService::UnInstall()
{
return m_impl->UnInstall();
}
int NTService::SetStartupType(SERVICE_STARTUP_TYPE type)
{
return m_impl->SetStartupType(type);
}
int NTService::UpdateDesc(const char *desc)
{
return m_impl->UpdateDesc(desc);
}
int NTService::Start(int argc, const char **argv)
{
return m_impl->Start(argc, argv);
}
int NTService::Stop()
{
return m_impl->Stop();
}
int NTService::GetCurrentStatus()
{
return m_impl->GetCurrentStatus();
}
int NTService:: Run(ServiceTask &service)
{
return m_impl->Run(service);
} NTServiceImpl::NTServiceImpl(const char *name,
bool canstop,
bool canshutdown,
bool canpausecontinue)
: m_name(name)
{
m_canstop = canstop;
m_canshutdown = canshutdown;
m_canpausecontinue = canpausecontinue;
} NTServiceImpl::~NTServiceImpl()
{
} bool NTServiceImpl::IsInstalled()
{
return NTServiceManager::IsInstalled(m_name.c_str());
} int NTServiceImpl::Install(const char *display_name, SERVICE_STARTUP_TYPE type)
{
return NTServiceManager::Install(m_name.c_str(), display_name, type);
} int NTServiceImpl::UnInstall()
{
return NTServiceManager::UnInstall(m_name.c_str());
} int NTServiceImpl::Start(int argc, const char **argv)
{
return NTServiceManager::Start(m_name.c_str(), argc, argv);
} int NTServiceImpl::Stop()
{
return NTServiceManager::Stop(m_name.c_str());
} int NTServiceImpl::SetStartupType(SERVICE_STARTUP_TYPE type)
{
return NTServiceManager::SetStartupType(m_name.c_str(), type);
} int NTServiceImpl::UpdateDesc(const char *desc)
{
return NTServiceManager::UpdateDesc(m_name.c_str(), desc);
} int NTServiceImpl::GetCurrentStatus()
{
return NTServiceManager::GetCurrentStatus(m_name.c_str());
} int NTServiceImpl::Run(ServiceTask &service)
{
NTServiceHandler::CreateInstance(m_name, m_canstop, m_canshutdown, m_canpausecontinue, service);
NTServiceHandler *handler = NTServiceHandler::GetInstance();
return handler ? handler->Run() : -;
} bool NTServiceManager::IsInstalled(const char *name)
{
assert(name); bool result = false;
SC_HANDLE scmanager = ;
SC_HANDLE service = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_QUERY_STATUS); __Cleanup:
if (service)
{
result = true;
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::Install(const char *name, const char *display_name, SERVICE_STARTUP_TYPE type)
{
assert(name && display_name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE);
if (!scmanager)
{
goto __Cleanup;
} char file_path[MAX_PATH] = {};
::GetModuleFileName(NULL, file_path, MAX_PATH); int startup_type = GetRealStartupType(type); service = CreateService(
scmanager, // SCM database
name, // name of service
display_name, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
startup_type, // start type
SERVICE_ERROR_NORMAL, // error control type
file_path, // path to service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password __Cleanup:
if (service)
{
result = ;
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::UnInstall(const char *name)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_STATUS status = {}; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_STOP|SERVICE_QUERY_STATUS|DELETE);
if (!service)
{
goto __Cleanup;
} if (ControlService(service, SERVICE_CONTROL_STOP, &status))
{
::Sleep(); while (QueryServiceStatus(service, &status))
{
if (status.dwCurrentState != SERVICE_STOP_PENDING)
{
break;
}
else
{
Sleep();
}
}
} if (DeleteService(service))
{
result = ;
} __Cleanup:
if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::SetStartupType(const char *name, SERVICE_STARTUP_TYPE type)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_CHANGE_CONFIG);
if (!service)
{
goto __Cleanup;
} int startup_type = GetRealStartupType(type); BOOL csc_result = ChangeServiceConfig(
service, // handle of service
SERVICE_NO_CHANGE, // service type: no change
startup_type, // service start type
SERVICE_NO_CHANGE, // error control: no change
NULL, // binary path: no change
NULL, // load order group: no change
NULL, // tag ID: no change
NULL, // dependencies: no change
NULL, // account name: no change
NULL, // password: no change
NULL); // display name: no change if (csc_result)
{
result = ;
} __Cleanup:
if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::UpdateDesc(const char *name, const char *desc)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_DESCRIPTION sd = {};
sd.lpDescription = (char *)desc; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_CHANGE_CONFIG);
if (!service)
{
goto __Cleanup;
} if (ChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &sd))
{
result = ;
} __Cleanup:
if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::Start(const char *name, int argc, const char **argv)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_STATUS status = {};
DWORD dwStartTickCount = ;
DWORD dwOldCheckPoint = ;
DWORD dwWaitTime = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_ALL_ACCESS);
if (!service)
{
goto __Cleanup;
} if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if(status.dwCurrentState!=SERVICE_STOPPED
&& status.dwCurrentState!=SERVICE_STOP_PENDING)
{
goto __Cleanup;
} dwStartTickCount = GetTickCount();
dwOldCheckPoint = status.dwCheckPoint;
while (status.dwCurrentState == SERVICE_STOP_PENDING)
{
dwWaitTime = status.dwWaitHint / ;
if(dwWaitTime < )
{
dwWaitTime = ;
}
else if (dwWaitTime > )
{
dwWaitTime = ;
}
::Sleep(dwWaitTime); if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCheckPoint > dwOldCheckPoint)
{
dwStartTickCount = GetTickCount();
dwOldCheckPoint = status.dwCheckPoint;
}
else
{
if ((GetTickCount()-dwStartTickCount) > status.dwWaitHint)
{
goto __Cleanup;
}
}
} if (!StartService(service, argc, argv))
{
goto __Cleanup;
} if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} dwStartTickCount = GetTickCount();
dwOldCheckPoint = status.dwCheckPoint;
while (status.dwCurrentState == SERVICE_START_PENDING)
{
dwWaitTime = status.dwWaitHint / ;
if(dwWaitTime < )
{
dwWaitTime = ;
}
else if (dwWaitTime > )
{
dwWaitTime = ;
}
::Sleep(dwWaitTime); if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCheckPoint > dwOldCheckPoint)
{
dwStartTickCount = GetTickCount();
dwOldCheckPoint = status.dwCheckPoint;
}
else
{
if ((GetTickCount()-dwStartTickCount) > status.dwWaitHint)
{
break;
}
}
} __Cleanup:
if (status.dwCurrentState==SERVICE_RUNNING)
{
result = ;
} if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::Stop(const char *name)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_STATUS status = {};
DWORD dwStartTime = GetTickCount();
DWORD dwTimeout = ;
DWORD dwWaitTime = ; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_STOP|SERVICE_QUERY_STATUS);
if (!service)
{
goto __Cleanup;
} if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCurrentState == SERVICE_STOPPED)
{
goto __Cleanup;
} while (status.dwCurrentState == SERVICE_STOP_PENDING)
{
dwWaitTime = status.dwWaitHint / ;
if(dwWaitTime < )
{
dwWaitTime = ;
}
else if (dwWaitTime > )
{
dwWaitTime = ;
}
::Sleep(dwWaitTime); if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCurrentState == SERVICE_STOPPED)
{
goto __Cleanup;
} if ((GetTickCount() - dwStartTime) > dwTimeout)
{
goto __Cleanup;
}
} if (!ControlService(service, SERVICE_CONTROL_STOP, &status))
{
goto __Cleanup;
} while (status.dwCurrentState != SERVICE_STOPPED)
{
::Sleep(status.dwWaitHint); if (!QueryServiceStatus(service, &status))
{
goto __Cleanup;
} if (status.dwCurrentState == SERVICE_STOPPED)
{
goto __Cleanup;
} if ( GetTickCount() - dwStartTime > dwTimeout )
{
goto __Cleanup;
}
} __Cleanup:
if (status.dwCurrentState == SERVICE_STOPPED)
{
result = ;
} if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::GetCurrentStatus(const char *name)
{
assert(name); int result = -;
SC_HANDLE scmanager = ;
SC_HANDLE service = ;
SERVICE_STATUS status = {}; scmanager = ::OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
if (!scmanager)
{
goto __Cleanup;
} service = ::OpenService(scmanager, name, SERVICE_QUERY_STATUS);
if (!service)
{
goto __Cleanup;
} if (QueryServiceStatus(service, &status))
{
result = status.dwCurrentState;
} __Cleanup:
if (service)
{
::CloseServiceHandle(service);
}
if (scmanager)
{
::CloseServiceHandle(scmanager);
} return result;
} int NTServiceManager::GetRealStartupType(SERVICE_STARTUP_TYPE type)
{
switch (type)
{
case SST_AUTO_START:
{
return SERVICE_AUTO_START;
}
case SST_DEMAND_START:
{
return SERVICE_DEMAND_START;
}
case SST_DISABLED:
default:
{
return SERVICE_DISABLED;
}
}
} NTServiceHandler::NTServiceHandler(const std::string &name,
bool canstop,
bool canshutdown,
bool canpausecontinue,
ServiceTask &service)
: m_name(name),
m_service(service)
{
memset(&m_status, , sizeof(SERVICE_STATUS));
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
m_status.dwCurrentState = SERVICE_START_PENDING;
m_status.dwWin32ExitCode = NO_ERROR;
m_status.dwServiceSpecificExitCode = ;
m_status.dwCheckPoint = ;
m_status.dwWaitHint = ; if (canstop)
{
m_status.dwControlsAccepted |= SERVICE_ACCEPT_STOP;
}
if (canshutdown)
{
m_status.dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
}
if (canpausecontinue)
{
m_status.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
} m_status_handle = ;
} NTServiceHandler::~NTServiceHandler()
{
} int NTServiceHandler::Run()
{
SERVICE_TABLE_ENTRY st[] =
{
{(LPSTR)m_name.c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceMainHandler},
{NULL, NULL}
}; return ::StartServiceCtrlDispatcher(st) ? : -;
} void NTServiceHandler::ServiceMainHandler(DWORD argc, LPSTR *argv)
{
NTServiceHandler *m_this = GetInstance();
if (m_this)
{
m_this->m_status_handle = RegisterServiceCtrlHandler(m_this->m_name.c_str(), (LPHANDLER_FUNCTION)ServiceCtrlHandler);
if (!m_this->m_status_handle)
{
return;
} m_this->NTS_Start(argc, argv);
}
} void NTServiceHandler::ServiceCtrlHandler(DWORD ctrl)
{
NTServiceHandler *m_this = GetInstance();
if (m_this)
{
switch (ctrl)
{
case SERVICE_CONTROL_STOP:
{
m_this->NTS_Stop();
}
break;
case SERVICE_CONTROL_PAUSE:
{
m_this->NTS_Pause();
}
break;
case SERVICE_CONTROL_CONTINUE:
{
m_this->NTS_Continue();
}
break;
case SERVICE_CONTROL_SHUTDOWN:
{
m_this->NTS_Shutdown();
}
break;
case SERVICE_CONTROL_INTERROGATE:
default:
break;
}
}
} void NTServiceHandler::NTS_Start(DWORD argc, LPSTR *argv)
{
try
{
SetServiceStatus(SERVICE_START_PENDING); if (OnInit(argc, argv) != )
{
exit();
} SetServiceStatus(SERVICE_RUNNING); OnStart(); SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
SetServiceStatus(SERVICE_STOPPED, dwError);
}
catch (...)
{
SetServiceStatus(SERVICE_STOPPED);
}
} void NTServiceHandler::NTS_Stop()
{
DWORD dwOriginalState = m_status.dwCurrentState; try
{
SetServiceStatus(SERVICE_STOP_PENDING); OnStop(); SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
dwError = ;
SetServiceStatus(dwOriginalState);
}
catch (...)
{
SetServiceStatus(dwOriginalState);
}
} void NTServiceHandler::NTS_Pause()
{
try
{
SetServiceStatus(SERVICE_PAUSE_PENDING); OnPause(); SetServiceStatus(SERVICE_PAUSED);
}
catch (DWORD dwError)
{
dwError = ;
SetServiceStatus(SERVICE_RUNNING);
}
catch (...)
{
SetServiceStatus(SERVICE_RUNNING);
}
} void NTServiceHandler::NTS_Continue()
{
try
{
SetServiceStatus(SERVICE_CONTINUE_PENDING); OnContinue(); SetServiceStatus(SERVICE_RUNNING);
}
catch (DWORD dwError)
{
dwError = ;
SetServiceStatus(SERVICE_PAUSED);
}
catch (...)
{
SetServiceStatus(SERVICE_PAUSED);
}
} void NTServiceHandler::NTS_Shutdown()
{
try
{
OnShutdown(); SetServiceStatus(SERVICE_STOPPED);
}
catch (DWORD dwError)
{
dwError = ;
}
catch (...)
{
}
} void NTServiceHandler::SetServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
assert(m_status_handle); static DWORD dwCheckPoint = ; m_status.dwCurrentState = dwCurrentState;
m_status.dwWin32ExitCode = dwWin32ExitCode;
m_status.dwWaitHint = dwWaitHint; if (dwCurrentState==SERVICE_RUNNING
|| dwCurrentState==SERVICE_STOPPED)
{
m_status.dwCheckPoint = ;
}
else
{
m_status.dwCheckPoint = ++dwCheckPoint;
} ::SetServiceStatus(m_status_handle, &m_status);
} int NTServiceHandler::OnInit(int argc, char **argv)
{
return m_service.OnInit(argc, argv);
} void NTServiceHandler::OnStart()
{
m_service.OnStart();
} void NTServiceHandler::OnStop()
{
m_service.OnStop();
} void NTServiceHandler::OnPause()
{
m_service.OnPause();
} void NTServiceHandler::OnContinue()
{
m_service.OnContinue();
} void NTServiceHandler::OnShutdown()
{
m_service.OnShutdown();
}
Windows NTService 后台框架封装的更多相关文章
- Magicodes.WeiChat——后台JS框架封装
Magicodes.WeiChat同时也致力于提高后台开发效率,因此对在后台前端这块也做了一定的封装.我们先来说说主要的框架JS——mwc.js和mwc_elements.js.这两个JS文件位于Sc ...
- 打造颠覆你想象中的高性能,轻量级的webform框架---js直接调后台的封装(第三天)
如果你没有看我第二天写的内容的,我想你是看不懂的!!!! 好了,废话不多说,怎么才能让我们的代码变得牛逼起来呢?怎么封装我们的代码呢?我们不可能 每个页面都需要那样写吧,那我们来一步一步来封装 我们的 ...
- springmvc跨域+token验证(app后台框架搭建二)
这是app后台框架搭建的第二课,主要针对app应用是跨域的运用,讲解怎么配置跨域服务:其次讲解怎么进行token验证,通过拦截器设置token验证和把token设置到http报文中.主要有如下: ...
- Spring Boot(5)一个极简且完整的后台框架
https://blog.csdn.net/daleiwang/article/details/75007588 Spring Boot(5)一个极简且完整的后台框架 2017年07月12日 11:3 ...
- 用ladon框架封装Python为Webservice接口以及调用接口的方法
一.用ladon框架封装Python为Webservice接口 功能实现的同时,希望将接口开放给别人,而封装python接口的一个再简单不过的框架Ladon,而且提供不同的协议,包括SOAP和Json ...
- Directx11 教程(2) 基本的windows应用程序框架(2)
原文:Directx11 教程(2) 基本的windows应用程序框架(2) 在本教程中,我们把前面一个教程的代码,进行封装.把初始化函数,Run函数,窗口回调函数,ShutdownWind ...
- EasyUI+MVC-搭建后台框架
一.EasyUI简介: jQuery EasyUI是一组基于jQuery的UI插件集合体,而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面. 官方网站:h ...
- android 开发 - 使用okhttp框架封装的开发框架
概述 在android开发中经常要访问网络,目前最流行的网络访问框架就是Okhttp了,然而我们在具体使用时,往往仍然需要二次封装.我使用Builder设计模式进行了封装形成oknet开源库. 介绍 ...
- jquery easyui+layer后台框架
最近使用jquery easyui搭建了一个后台框架,以方便以后使用 上图先: 下载地址:CSDN下载
随机推荐
- [LeetCode][Python]Longest Palindromic Substring
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com'https://oj.leetcode.com/problems/longest ...
- JAVA实现字符串反转,借助字符数组实现
public static String reverseStr(String str) { int len = str.length(); char ch[] = str.toCharArray(); ...
- Qt编写端口扫描工具
Qt提供了QTcpSocket类,可以方便地建立TCP连接.利用这一功能,Maxiee编写了一个简单地端口扫描工具. 软件的功能就是,扫描某一网段的固定端口,如80端口,若目的地址开放了这一端口,那么 ...
- Android牛博
Android实现伸缩弹力分布菜单效果 摘要: 本文介绍下在Android中实现伸缩弹力分布菜单效果.关于这种菜单效果在IPhone中比较常见,效果比较酷.那么在Android中实现只是一种简单的模仿 ...
- 转换成CSV文件、Word、Excel、PDF等的方法--读取CSV文件的方法
1. 转换成CSV文件: http://www.dotnetgallery.com/lab/resource93-Export-to-CSV-file-from-Data-Table-in-Aspne ...
- java正则表达式,将字符串中\后的第一个字母变成大写
java正则表达式,将字符串中\后的第一个字母变成大写 例子是比较简单,注意的是java中的“\\”意义是:我要插入一个正则表达式的反斜线,所以其后面的字符有特殊有意义.所以普通反斜线应该是" ...
- bool operator==(const Array&)const; 这最后一个const 是做什么用的
字符重载也是个函数,在函数末尾加CONST 这样的函数叫常成员函数.常成员函数可以理解为是一个“只读”函数,它既不能更改数据成员的值,也不能调用那些能引起数据成员值变化的成员函数,只能调用const成 ...
- [C#参考]细说进程、应用程序域与上下文之间的关系
原文转载链接:http://www.cnblogs.com/leslies2/archive/2012/03/06/2379235.html Written by:风尘浪子 引言 本文主要是介绍进程( ...
- win8 iis安装及网站发布(转)
系统:win8 环境:vs2012 一:安装IIS 比较win7的安装来说,多选了几个钩钩,不然会报错,偶就遇到这样的错误. 控制面板->程序和功能->启动和关闭windows功能,钩钩图 ...
- JavaScript中的闭包理解
原创文章,转载请注明:JavaScript中的闭包理解 By Lucio.Yang 1.JavaScript闭包 在小学期开发项目的时候,用node.js开发了服务器,过程中遇到了node.js的第 ...