对于后台运行的程序,比如基于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 后台框架封装的更多相关文章

  1. Magicodes.WeiChat——后台JS框架封装

    Magicodes.WeiChat同时也致力于提高后台开发效率,因此对在后台前端这块也做了一定的封装.我们先来说说主要的框架JS——mwc.js和mwc_elements.js.这两个JS文件位于Sc ...

  2. 打造颠覆你想象中的高性能,轻量级的webform框架---js直接调后台的封装(第三天)

    如果你没有看我第二天写的内容的,我想你是看不懂的!!!! 好了,废话不多说,怎么才能让我们的代码变得牛逼起来呢?怎么封装我们的代码呢?我们不可能 每个页面都需要那样写吧,那我们来一步一步来封装 我们的 ...

  3. springmvc跨域+token验证(app后台框架搭建二)

    这是app后台框架搭建的第二课,主要针对app应用是跨域的运用,讲解怎么配置跨域服务:其次讲解怎么进行token验证,通过拦截器设置token验证和把token设置到http报文中.主要有如下:   ...

  4. Spring Boot(5)一个极简且完整的后台框架

    https://blog.csdn.net/daleiwang/article/details/75007588 Spring Boot(5)一个极简且完整的后台框架 2017年07月12日 11:3 ...

  5. 用ladon框架封装Python为Webservice接口以及调用接口的方法

    一.用ladon框架封装Python为Webservice接口 功能实现的同时,希望将接口开放给别人,而封装python接口的一个再简单不过的框架Ladon,而且提供不同的协议,包括SOAP和Json ...

  6. Directx11 教程(2) 基本的windows应用程序框架(2)

    原文:Directx11 教程(2) 基本的windows应用程序框架(2)      在本教程中,我们把前面一个教程的代码,进行封装.把初始化函数,Run函数,窗口回调函数,ShutdownWind ...

  7. EasyUI+MVC-搭建后台框架

    一.EasyUI简介: jQuery EasyUI是一组基于jQuery的UI插件集合体,而jQuery EasyUI的目标就是帮助web开发者更轻松的打造出功能丰富并且美观的UI界面. 官方网站:h ...

  8. android 开发 - 使用okhttp框架封装的开发框架

    概述 在android开发中经常要访问网络,目前最流行的网络访问框架就是Okhttp了,然而我们在具体使用时,往往仍然需要二次封装.我使用Builder设计模式进行了封装形成oknet开源库. 介绍 ...

  9. jquery easyui+layer后台框架

    最近使用jquery easyui搭建了一个后台框架,以方便以后使用 上图先: 下载地址:CSDN下载

随机推荐

  1. java把函数作为参数传递

    public class Tool { public void a()// /方法a { System.out.print("tool.a()..."); } public voi ...

  2. [Leetcode][Python]29: Divide Two Integers

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 29: Divide Two Integershttps://oj.leetc ...

  3. [Leetcode][Python]24: Swap Nodes in Pairs

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 24: Swap Nodes in Pairshttps://oj.leetc ...

  4. Android的UI两大基石

        说到Android的UI就不得不从一切的开始View开始说.     让我们从Android Developer上的View的Overview和UI Overview来开始吧.     Cla ...

  5. jQuery easyUI Pagination控件自定义div分页(不用datagrid)

    一般后台管理页面分页是通过datagrid加Pagination分页,但是如果前台页面没有用表格,例如博客的文章列表从上到下一般是到div分页, 这时如果还要用Pagination,则可以这样: 页面 ...

  6. Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!)

    Sql Server 2008 卸载重新安装失败的解决办法!(多次偿试,方法均有效!) 1.控制面板中卸载所有带sql server的程序. 2.在C盘C:\Program Files中sqlserv ...

  7. C与C++不同

    常量表示方法不同 C不支持引用,C++支持 注释不同,C89不支持单行注释 (++i)++在C中不合法 (a=3)=4在C中不合法 不能在for循环头部定义变量 C++注重类型,强类型,严格检查类型 ...

  8. 【转】Python3.x移除了callable内建函数

    原文地址:http://www.cnblogs.com/elvisxu/archive/2010/10/26/1861958.html 最近学习Python的时候,在Python3下跑<Dive ...

  9. Javascript 基础编程练习一

    Javascript 基础互动编程,这篇练习结合了function 函数名(), onclick 时间, prompt输入窗口, window.open和confirm窗口, 任务 1.新窗口打开时弹 ...

  10. 使用Spire PDF for .NET将HTML转换成PDF文档

    目录 开发环境说明 Spire PDF for .NET (free edition)体验 资源下载 开发环境说明 Microsoft Visual Studio 2013 Ultimate Edit ...