将一个可执行应用程序作为一个服务,你的main函数就相当于此处的run,而这个run作为
回调函数的一部分被执行。作为服务的程序一般不会是执行一遍就退出的,即run函数是会被阻塞的。
如果你的run函数执行一次就退出的话,那么它不适合作为服务。
怎样运行这个应用程序?
1>编译出可执行文件.exe;
2>运行->cmd->cd到exe目录;
3>首先安装,MyService.exe install, 然后注册,MyService.exe;
4>打开服务,MyService.exe open;
如下程序,打开服务后会在C盘生成test.txt文件并且从1开始每秒打印一个+1的数字。
我这里只实现了打开(open), 停止(stop), 重启(restart)这三个功能
要删除这个服务可以用(需要重启系统):sc delete MyService
参考地址:http://blog.youkuaiyun.com/zhongguoren666/article/details/7580773
环境:vs2008+sp1, 没有安装sp1编译不通过,不能使用C++ tr1里面的bind和function。
// WinService.h
#include <windows.h>
#include <functional>
class WinService
{
public:
explicit WinService(const char *name);
BOOL start(std::tr1::function<void()> run);
int install();
BOOL open();
BOOL stop();
private:
WinService(const WinService&);
WinService& operator=(const WinService&);
static void WINAPI myServiceMain(DWORD argc, LPTSTR * argv);
static void WINAPI serviceCtrlHandler(DWORD dwControl);
SC_HANDLE getHandle() const;
static char name_[MAX_PATH];
static SERVICE_STATUS serviceStatus_;
static SERVICE_STATUS_HANDLE serviceStatusHandle_;
static std::tr1::function<void()> start_fun_;
static std::tr1::function<void()> stop_fun_;
};
// WinService.cpp
#include "WinService.h"
#include <assert.h>
char WinService::name_[MAX_PATH] = {0};
SERVICE_STATUS WinService::serviceStatus_;
SERVICE_STATUS_HANDLE WinService::serviceStatusHandle_;
std::tr1::function<void()> WinService::start_fun_;
std::tr1::function<void()> WinService::stop_fun_;
WinService::WinService(const char *name)
{
assert(NULL != name);
memcpy(name_, name, min(strlen(name), MAX_PATH-1));
}
BOOL WinService::start(std::tr1::function<void()> run)
{
SERVICE_TABLE_ENTRY serviceTableEntry[] = {
{name_, myServiceMain},
{NULL, NULL}
};
start_fun_ = run;
return ::StartServiceCtrlDispatcher(serviceTableEntry);
}
int WinService::install()
{
SC_HANDLE handle= ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
char szFilename[MAX_PATH] = {0};
DWORD dwErr = 0;
::GetModuleFileName(NULL, szFilename, MAX_PATH);
SC_HANDLE hService = ::CreateService(handle, name_,
name_, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, szFilename, NULL,
NULL, NULL, NULL, NULL);
::CloseServiceHandle(hService);
::CloseServiceHandle(handle);
if (NULL == hService)
{
dwErr = ::GetLastError();
}
return dwErr;
}
BOOL WinService::open()
{
return StartService(getHandle(), 0, NULL);
}
BOOL WinService::stop()
{
return ControlService(getHandle(), SERVICE_CONTROL_STOP, &serviceStatus_);
}
void WINAPI WinService::myServiceMain(DWORD argc, LPTSTR * argv)
{
serviceStatus_.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus_.dwCurrentState = SERVICE_START_PENDING;
serviceStatus_.dwControlsAccepted = SERVICE_ACCEPT_STOP;
serviceStatus_.dwWin32ExitCode = 0;
serviceStatus_.dwServiceSpecificExitCode = 0;
serviceStatus_.dwCheckPoint = 0;
serviceStatus_.dwWaitHint = 0;
serviceStatusHandle_ = ::RegisterServiceCtrlHandler(name_, serviceCtrlHandler);
if (serviceStatusHandle_ == (SERVICE_STATUS_HANDLE)0)
{
return;
}
SetServiceStatus(serviceStatusHandle_, &serviceStatus_);
serviceStatus_.dwWin32ExitCode = S_OK;
serviceStatus_.dwCheckPoint = 0;
serviceStatus_.dwWaitHint = 0;
serviceStatus_.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(serviceStatusHandle_, &serviceStatus_);
if (start_fun_)
{
start_fun_();
}
serviceStatus_.dwCurrentState = SERVICE_STOPPED;
serviceStatus_.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
serviceStatus_.dwServiceSpecificExitCode = 1;
::SetServiceStatus(serviceStatusHandle_, &serviceStatus_);
}
void WINAPI WinService::serviceCtrlHandler(DWORD dwControl)
{
switch (dwControl)
{
case SERVICE_CONTROL_PAUSE:
serviceStatus_.dwCurrentState = SERVICE_PAUSE_PENDING;
::SetServiceStatus(serviceStatusHandle_, &serviceStatus_);
serviceStatus_.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
serviceStatus_.dwCurrentState = SERVICE_CONTINUE_PENDING;
::SetServiceStatus(serviceStatusHandle_, &serviceStatus_);
serviceStatus_.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
serviceStatus_.dwCurrentState = SERVICE_STOP_PENDING;
::SetServiceStatus(serviceStatusHandle_, &serviceStatus_);
serviceStatus_.dwCurrentState = SERVICE_STOPPED;
break;
case SERVICE_CONTROL_SHUTDOWN:
break;
case SERVICE_CONTROL_INTERROGATE:
serviceStatus_.dwCurrentState = SERVICE_RUNNING;
break;
}
::SetServiceStatus(serviceStatusHandle_, &serviceStatus_);
}
SC_HANDLE WinService::getHandle() const
{
SC_HANDLE handle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (handle)
{
return OpenService(handle, name_, SERVICE_ALL_ACCESS);
}
return NULL;
}
// main.cpp
#include "WinService.h"
#include <fstream>
#include <iostream>
void run()
{
static int count = 0;
std::fstream fs("c:\\test.txt", std::ios::out|std::ios::trunc);
if (!fs.bad())
{
while (1)
{
fs << ++count << std::endl;
::Sleep(1000);
fs.flush();
}
fs.close();
}
}
int main(int argc, char *argv[])
{
WinService myService("AppServer1");
if (2==argc && 0==_stricmp(argv[1], "install"))
{
int ret = myService.install();
std::cout << "install, ret code:" << ret << std::endl;
}
else if (2==argc && 0==_stricmp(argv[1], "open"))
{
BOOL bret = myService.open();
std::cout << "open, ret code:" << ((bret==TRUE)?0:-1) << std::endl;
}
else if (2==argc && 0==_stricmp(argv[1], "stop"))
{
BOOL bret = myService.stop();
std::cout << "stop, ret code:" << ((bret==TRUE)?0:-1) << std::endl;
}
else if (2==argc && 0==_stricmp(argv[1], "restart"))
{
BOOL bret = FALSE;
if (myService.stop())
{
bret = myService.open();
}
std::cout << "restart, ret code:" << ((bret==TRUE)?0:-1) << std::endl;
}
else
{
myService.start(std::tr1::bind(run));
}
return 0;
}