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下载
随机推荐
- java把函数作为参数传递
public class Tool { public void a()// /方法a { System.out.print("tool.a()..."); } public voi ...
- [Leetcode][Python]29: Divide Two Integers
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 29: Divide Two Integershttps://oj.leetc ...
- [Leetcode][Python]24: Swap Nodes in Pairs
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 24: Swap Nodes in Pairshttps://oj.leetc ...
- Android的UI两大基石
说到Android的UI就不得不从一切的开始View开始说. 让我们从Android Developer上的View的Overview和UI Overview来开始吧. Cla ...
- jQuery easyUI Pagination控件自定义div分页(不用datagrid)
一般后台管理页面分页是通过datagrid加Pagination分页,但是如果前台页面没有用表格,例如博客的文章列表从上到下一般是到div分页, 这时如果还要用Pagination,则可以这样: 页面 ...
- Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!)
Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!) 1.控制面板中卸载所有带sql server的程序. 2.在C盘C:\Program Files中sqlserv ...
- C与C++不同
常量表示方法不同 C不支持引用,C++支持 注释不同,C89不支持单行注释 (++i)++在C中不合法 (a=3)=4在C中不合法 不能在for循环头部定义变量 C++注重类型,强类型,严格检查类型 ...
- 【转】Python3.x移除了callable内建函数
原文地址:http://www.cnblogs.com/elvisxu/archive/2010/10/26/1861958.html 最近学习Python的时候,在Python3下跑<Dive ...
- Javascript 基础编程练习一
Javascript 基础互动编程,这篇练习结合了function 函数名(), onclick 时间, prompt输入窗口, window.open和confirm窗口, 任务 1.新窗口打开时弹 ...
- 使用Spire PDF for .NET将HTML转换成PDF文档
目录 开发环境说明 Spire PDF for .NET (free edition)体验 资源下载 开发环境说明 Microsoft Visual Studio 2013 Ultimate Edit ...