windows服务程序

有时候需要windows服务程序来执行一些操作, 比如需要在登陆前启动, 不想被杀软判为自启动, 当然还是能被发现, 但是杀软的普通清理时不会清理的。但是服务程序不能进行界面交互, 因为他不属于用户界面。他只是在后台默默的启动, 运行, 对于收集数据, 后台更新再合适不过了。 一个服务程序的简单写法:

SERVICE_STATUS_HANDLE hServiceStatus;
SERVICE_STATUS ServiceStatus; 

void WINAPI ServiceHandler(DWORD fdwControl)  
{  
	switch(fdwControl)   
	{  
	case SERVICE_CONTROL_STOP:  
	case SERVICE_CONTROL_SHUTDOWN:  
		ServiceStatus.dwWin32ExitCode = 0;   
		ServiceStatus.dwCurrentState  = SERVICE_STOPPED;   
		ServiceStatus.dwCheckPoint    = 0;   
		ServiceStatus.dwWaitHint      = 0;  
		break;   
	default:  
		return;   
	};  
	if (!SetServiceStatus(hServiceStatus,  &ServiceStatus))   
	{   
		DWORD nError = GetLastError();  
	}   
}  
void WINAPI ServiceMain(DWORD argc, char**argv)
{
	ServiceStatus.dwCurrentState=SERVICE_START_PENDING;
	ServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;

	//注册服务控制函数
	hServiceStatus=RegisterServiceCtrlHandler(L"UlogReport",ServiceHandler);
	if(!hServiceStatus)
	{
		return;
	}

	//设置服务状态
	SetServiceStatus(hServiceStatus,&ServiceStatus);

	ServiceStatus.dwWin32ExitCode=S_OK;
	ServiceStatus.dwCheckPoint=0;
	ServiceStatus.dwWaitHint=0;
	ServiceStatus.dwCurrentState=SERVICE_RUNNING;
	SetServiceStatus(hServiceStatus,&ServiceStatus);

	//guid
	TCHAR szGuid[50] = {0};
	Base::GUID::GetGuid(szGuid, 50);

	//osversion
	CString szOSVer = L"0.0";
	OSVERSIONINFOEX osVer;
	osVer.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
	if (GetVersionEx((OSVERSIONINFO *)&osVer))
	{
		szOSVer.Format(L"%d.%d", osVer.dwMajorVersion,osVer.dwMinorVersion);
	}
	
	//supplyid
	TCHAR szModule[MAX_PATH] = {0};
	GetModuleFileName(NULL, szModule, MAX_PATH);
	PathRemoveFileSpec(szModule);
	PathAppend(szModule, L"record.ini");
	CIniFile iniRecord;
	iniRecord.SetPath(szModule);
	CString szSuppyID = iniRecord.GetKeyValue(_T("Supply"),_T("id"));
	
	//install software
	CString softwares = iniRecord.GetKeyValue(_T("installsoft"),_T("sofid"));

	char szTypeSend[]="install";
	CStringA csMsgSend;
	csMsgSend.Format("guid:%ws;os:%ws;supplyid:%ws;software:%ws;", szGuid, szOSVer, szSuppyID,softwares);
	BYTE typelen = strlen(szTypeSend);
	DWORD msgLen = csMsgSend.GetLength();
	BYTE appID = 3;

	int packLen = sizeof(MSG_PACK) + typelen + msgLen + 1;
	MSG_PACK* msg = (MSG_PACK*) new BYTE[packLen];
	memset((char*)msg,'\n',packLen);
	msg->typeLen = typelen;
	msg->msgLen = htonl(msgLen);
	msg->appID = appID;

	memcpy((BYTE*)(msg->szInfo), szTypeSend ,typelen);
	memcpy((BYTE*)(msg->szInfo)+typelen, csMsgSend.GetString(), msgLen);
	
	char szlog[MAX_PATH] = {0};
	GetTempPathA(MAX_PATH, szlog);
	PathAppendA(szlog, "logContent.txt");
	std::ofstream ofile(szlog);
	ofile<<csMsgSend.GetString()<<std::endl;
	ofile.close();
	CLogReport::Instance()->Send((char*)msg, packLen);
	CLogReport::Release();
	//退出服务
	ServiceStatus.dwCurrentState=SERVICE_STOPPED;
	SetServiceStatus(hServiceStatus,&ServiceStatus);
	ShellRun(L"cmd.exe", L"/c sc delete UlogReport");
	if (GetExecDir() == _T("C:\\Program Files\\Common Files\\BDInstall"))
	{
		std::ofstream ofile("C:\\Program Files\\Common Files\\BDInstall\\CleanTemp.bat");
		ofile<<"cd..&rd /s /q \"%~dp0\"&exit";
		ofile.close();
		WinExec("C:\\Program Files\\Common Files\\BDInstall\\CleanTemp.bat",SW_HIDE);
	}
	exit(0);
}
int _tmain(int argc, _TCHAR* argv[])
{
	SERVICE_TABLE_ENTRY dispatchTable[] =
	{
		{ L"UlogReport", (LPSERVICE_MAIN_FUNCTION)ServiceMain},
		{NULL, NULL}
	};

	// Call the service control dispatcher with our entry table
	if (!StartServiceCtrlDispatcher(dispatchTable))
	{
		return GetLastError();
	}
	return 0;
}
_tmain不用说, 不管是什么程序都需要这么一个入口, 要不操作系统该如何去启动这个程序。

ServiceMain就是用来被调用的主函数, 只有用StartServiceCtrlDispatcher调用这个主函数, 才会被服务管理程序认可, 否则就会被服务管理程序终止掉。

ServiceHandler是提供给服务管理器的控制接口, 就是能够在服务管理器中手动启动, 停止的函数。


服务程序写好了,现在就该把他交给服务管理器, 以便能够在系统启动时启动, 有两种方法:

1. cmd命令。这个最方便, 一句命令行就能搞定。 

<span style="white-space:pre">	</span>CString strCmd;
	strCmd.Format(L"/c sc create UlogReport binPath= \"%s\" start= auto", GetExecDir()+_T("\\Ulogsvc.exe"));
	ShellRun(L"cmd.exe", strCmd);
2. windows API

OpenSCManager打开服务管理器, 然后CreateService。最后CloseServiceHandle关闭句柄。


创建完成之后启动服务, 同样有两种方法cmd和API:

1.ShellRun(L"cmd.exe", L"/c sc start UlogReport");

2.api需要3步:

OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); 

OpenService( schSCManager, pName, SERVICE_ALL_ACCESS);

StartService(schService,nArg,(LPCTSTR*)pArg));


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值