将可执行应用程序作为服务运行

将一个可执行应用程序作为一个服务,你的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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值