VC++使用服务做守护进程的示例(转载)
转载:http://blog.csdn.net/zdy0_2004/article/details/40461571
#define _WIN32_WINNT 0x502
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <Shlwapi.h>
#include <WtsApi32.h>
#include <UserEnv.h>
#include <iostream>
#include <fstream>
#include <atlbase.h> static const char* const lpServiceName = "ProtectService";
static SERVICE_STATUS_HANDLE hServiceStatus = NULL;
static SERVICE_STATUS ServiceStatus = {};
static char szCurDir[MAX_PATH+] = {};
static bool bRun = false;
static HANDLE hProcess = NULL;
static FILE* fLog = NULL;
static std::ofstream ofs_log; bool InstallService();
VOID WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv);
VOID WINAPI HandlerFunc(DWORD dwControl);
HANDLE RunAsLoggedUser(const char* lpPath,char* lpCmdLine);
void WorkFunc(); int main(int argc, char **argv)
{
GetModuleFileName(NULL,szCurDir,MAX_PATH);
*strrchr(szCurDir,'\\') = '\0'; char szLogPath[MAX_PATH+];
sprintf(szLogPath,"%s\\Service.log",szCurDir);
fLog = fopen(szLogPath,"a+");
setvbuf(fLog,NULL,_IONBF,); ofs_log.open(szLogPath,std::ios::app); SERVICE_TABLE_ENTRY ServiceTable[];
char szBuffer[];
strcpy(szBuffer,lpServiceName);
ServiceTable[].lpServiceName = szBuffer;
ServiceTable[].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain; ServiceTable[].lpServiceName = NULL;
ServiceTable[].lpServiceProc = NULL; // 启动服务的控制分派机线程
if (!StartServiceCtrlDispatcher(ServiceTable))
{
ofs_log<<"程序不是以服务方式启动"<<std::endl;
std::cout<<"程序不是以服务方式启动,要创建服务并启动吗?y/n:";
if (getchar() == 'y')
{
// 安装服务
if (!InstallService())
{
ofs_log<<"安装服务失败"<<std::endl;
std::cout<<"安装服务失败,具体原因请查看日志"<<std::endl;
return ;
}
ofs_log<<"安装服务成功"<<std::endl;
} }
return ;
} bool InstallService()
{
SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if (!hSCManager)
{
ofs_log<<"OpenSCManager失败,错误码为:"<<GetLastError()<<std::endl;
return false;
} SC_HANDLE hService = OpenService(hSCManager,lpServiceName,SERVICE_QUERY_CONFIG);
if (hService)
{
ofs_log<<"服务已经存在"<<std::endl;
CloseServiceHandle(hSCManager);
CloseServiceHandle(hService);
return false;
} char szPath[MAX_PATH+];
GetModuleFileName(NULL,szPath,MAX_PATH);
hService = CreateService(hSCManager,
lpServiceName,
lpServiceName,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
szPath,
NULL,
NULL,
NULL,
NULL,
NULL);
if (!hService)
{
ofs_log<<"CreateService失败,错误码为"<<GetLastError()<<std::endl;
CloseServiceHandle(hSCManager);
return false;
} if (!StartService(hService,,NULL))
{
ofs_log<<"服务安装成功,但是启动服务失败,错误码为:"<<GetLastError()<<std::endl;
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return false;
} CloseServiceHandle(hService);
CloseServiceHandle(hSCManager); return true;
} VOID WINAPI ServiceMain( DWORD dwArgc,LPTSTR *lpszArgv )
{
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP;
hServiceStatus = RegisterServiceCtrlHandler(lpServiceName,HandlerFunc);
if (!hServiceStatus)
{
ofs_log<<"RegisterServiceCtrlHandler失败,错误码为:"<<GetLastError()<<std::endl;
return;
}
if (!SetServiceStatus(hServiceStatus,&ServiceStatus))
{
ofs_log<<"SetServiceStatus失败,错误码为:"<<GetLastError()<<std::endl;
return;
} bRun = true;
WorkFunc();
} VOID WINAPI HandlerFunc( DWORD dwControl )
{
ofs_log<<"收到服务消息:"<<dwControl<<std::endl; if (dwControl == SERVICE_CONTROL_STOP || dwControl == SERVICE_CONTROL_SHUTDOWN)
{
// 停止服务
ofs_log<<"服务停止"<<std::endl;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
bRun = false;
if (hProcess)
{
TerminateProcess(hProcess,);
}
} SetServiceStatus(hServiceStatus,&ServiceStatus);
} HANDLE RunAsCreator(const char* lpPath, char* lpCmdLine)
{
if (!PathFileExists(lpPath))
{
ofs_log<<"指定的要启动的程序不存在"<<std::endl;
return NULL;
} char szSubProcCurDir[MAX_PATH];
strcpy(szSubProcCurDir,lpPath);
*strrchr(szSubProcCurDir,'\\') = '\0'; STARTUPINFO si = {};
PROCESS_INFORMATION pi = {};
si.cb = sizeof(si); if (!CreateProcess(lpPath,lpCmdLine,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,NULL,szSubProcCurDir,&si,&pi))
{
ofs_log<<"CreateProcess失败,错误码为:"<<GetLastError()<<std::endl;
return NULL;
} if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
{
CloseHandle(pi.hThread);
} return pi.hProcess;
} HANDLE RunAsLoggedUser( const char* lpPath,char* lpCmdLine )
{
if (!PathFileExists(lpPath))
{
ofs_log<<"指定的要启动的程序不存在"<<std::endl;
return NULL;
} DWORD dwSid = WTSGetActiveConsoleSessionId();
ofs_log<<"当前登录用户ID为:"<<dwSid<<std::endl; HANDLE hExistingToken = NULL;
if (!WTSQueryUserToken(dwSid,&hExistingToken))
{
ofs_log<<"WTSQueryUserToken失败,错误码为:"<<GetLastError()<<std::endl;
return NULL;
} HANDLE hNewToken = NULL;
if (!DuplicateTokenEx(hExistingToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hNewToken))
{
ofs_log<<"DuplicateTokenEx失败,错误码为:"<<GetLastError()<<std::endl;
CloseHandle(hExistingToken);
return NULL;
}
CloseHandle(hExistingToken); LPVOID pEnv = NULL;
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
if (CreateEnvironmentBlock(&pEnv,hNewToken,FALSE))
{
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
} STARTUPINFO si = {};
PROCESS_INFORMATION pi = {};
si.cb = sizeof(si);
si.lpDesktop = "WinSta0\\Default"; char szSubProcCurDir[MAX_PATH+];
strcpy(szSubProcCurDir,lpPath);
*strrchr(szSubProcCurDir,'\\') = '\0'; if (!CreateProcessAsUser(hNewToken,lpPath,lpCmdLine,NULL,NULL,FALSE,dwCreationFlags,pEnv,szSubProcCurDir,&si,&pi))
{
ofs_log<<"CreateProcessAsUser失败,错误码为:"<<GetLastError()<<std::endl;
if (pEnv)
{
DestroyEnvironmentBlock(pEnv);
}
return NULL;
} if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
{
CloseHandle(pi.hThread);
} if (pEnv)
{
DestroyEnvironmentBlock(pEnv);
} return pi.hProcess;
} HANDLE RunAsSpecifiedUser(const char* lpUserName,const char* lpPassword,const char* lpPath,char* lpCmdLine)
{
if (!PathFileExists(lpPath))
{
ofs_log<<"指定的要启动的程序不存在"<<std::endl;
return NULL;
} HANDLE hExistingToken = NULL;
if (!LogonUser(lpUserName,NULL,lpPassword,LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&hExistingToken))
{
ofs_log<<"LogonUser失败,错误码为:"<<GetLastError()<<std::endl;
return NULL;
} HANDLE hNewToken = NULL;
if (!DuplicateTokenEx(hExistingToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hNewToken))
{
ofs_log<<"DuplicateTokenEx失败,错误码为:"<<GetLastError()<<std::endl;
CloseHandle(hExistingToken);
return NULL;
}
CloseHandle(hExistingToken); LPVOID pEnv = NULL;
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
if (CreateEnvironmentBlock(&pEnv,hNewToken,FALSE))
{
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
} STARTUPINFO si = {};
PROCESS_INFORMATION pi = {};
si.cb = sizeof(si);
//si.lpDesktop = "WinSta0\\Default"; char szSubProcCurDir[MAX_PATH+];
strcpy(szSubProcCurDir,lpPath);
*strrchr(szSubProcCurDir,'\\') = '\0'; if (!CreateProcessAsUser(hNewToken,lpPath,lpCmdLine,NULL,NULL,FALSE,dwCreationFlags,pEnv,szSubProcCurDir,&si,&pi))
{
ofs_log<<"CreateProcessAsUser失败,错误码为:"<<GetLastError()<<std::endl;
if (pEnv)
{
DestroyEnvironmentBlock(pEnv);
}
return NULL;
} if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
{
CloseHandle(pi.hThread);
} if (pEnv)
{
DestroyEnvironmentBlock(pEnv);
} return pi.hProcess;
} void WorkFunc()
{
char szIniPath[MAX_PATH+];
sprintf(szIniPath,"%s\\config.ini",szCurDir);
if (!PathFileExists(szCurDir))
{
ofs_log<<"配置文件不存在"<<std::endl;
} char szProgPath[MAX_PATH+];
GetPrivateProfileString("PROGRAM","PATH","",szProgPath,MAX_PATH,szIniPath);
char szCmdLine[];
GetPrivateProfileString("PROGRAM","CMD","",szCmdLine,,szIniPath);
int method = GetPrivateProfileInt("USERINFO","METHOD",,szIniPath);
char szUserName[];
char szPassword[];
GetPrivateProfileString("USERINFO","UID","",szUserName,,szIniPath);
GetPrivateProfileString("USERINFO","PWD","",szPassword,,szIniPath); while (bRun)
{
switch (method)
{
case :
hProcess = RunAsCreator(szProgPath,szCmdLine);
break;
case :
hProcess = RunAsLoggedUser(szProgPath,szCmdLine);
break;
case :
hProcess = RunAsSpecifiedUser(szUserName,szPassword,szProgPath,szCmdLine);
break;
default:
ofs_log<<"未知的启动方式:"<<method<<std::endl;
return;
} if (!hProcess)
{
ofs_log<<"创建进程失败失败"<<std::endl;
}
WaitForSingleObject(hProcess,INFINITE);
CloseHandle(hProcess);
hProcess = NULL;
ofs_log<<"被守护进程退出"<<std::endl;
Sleep();
}
}
VC++使用服务做守护进程的示例(转载)的更多相关文章
- Supervisor 为服务创建守护进程
今天需要再服务上部署一个.net 方面的项目:当时开启服务的命令只能在前台执行:使用nohub CMD &等放在后台开启服务都会宕机:所以搜寻了Supervisor 这个解决办法,为服务创建守 ...
- Linux控制服务和守护进程
目录 控制服务和守护进程 1.systemd 1.1.systemd简介 1.2.systemd的新特性 1.3.systemd的核心概念Unit 2.使用systemctl管理服务 控制服务和守护进 ...
- Linux_控制服务与守护进程
一.systemd 1.systemd简介 1️⃣:systemd是用户空间的第一个应用程序,即/sbin/init 2️⃣:init程序的类型: SysV风格:init(centos5),实现系统初 ...
- Windows守护进程简单示例
转载: https://blog.csdn.net/kikaylee/article/details/51395360 /* @描述:一个简单的Windows守护进程的例子(C++版本) @作者:ki ...
- PHP实现多进程并行操作,可做守护进程(转,备用)
<?php /** * 入口函数 * 将此文件保存为 ProcessOpera.php * 在terminal中运行 /usr/local/php/bin/php ProcessOpera.ph ...
- java实现服务端守护进程来监听客户端通过上传json文件写数据到hbase中
1.项目介绍: 由于大数据部门涉及到其他部门将数据传到数据中心,大部分公司采用的方式是用json文件的方式传输,因此就需要编写服务端和客户端的小程序了.而我主要实现服务端的代码,也有相应的客户端的测试 ...
- linux分享一:进程全攻略--守护进程(服务)
概括: 进程是程序的运行实例.进程对应一个唯一的进程PID, 统一程序的多个实例可以同时运行,他们的pid互不相同. 进程一般分为交互进程.批处理进程和守护进程(daemons)三类 一:什么是守护进 ...
- 深入理解Linux操作系统守护进程的意义
Linux服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程(daemons)来执行的.守护进程 ...
- 守护进程与Supervisor
博客链接:http://www.cnblogs.com/zhenghongxin/p/8676565.html 消息队列处理后台任务带来的问题 在系统稍微大些的时候,我们经常会用到消息队列(实现的方式 ...
随机推荐
- 修改机器名、IP对arcgis server、portal的影响?
修改机器名.IP是否对ArcGIS Server .Portal等有影响? 请教赛姐:修改IP对ArcGIS Server .Portal 无影响,不过建议将ArcGIS Server .Portal ...
- sublime安装install package
通过 https://sublime.wbond.net/Package%20Control.sublime-package 下载packageControl文件 下载完成后,打开sublime te ...
- LightOJ 1027 - A Dangerous Maze(求期望)
题目链接:http://lightoj.com/volume_showproblem.php?problem=1027 题意:又一个迷宫,有n个门,每个门又一个值num,如果num>0 说明在n ...
- 算法抽象及用Python实现具体算法
一.算法抽象 它们一般是在具体算法的基础上总结.提炼.分析出来的,再反过来用于指导解决其它问题.它们适用于某一类问题的解决,用辩 证法的观点看,抽象的算法和具体的算法就是抽象与具体.普遍性与特殊性.共 ...
- python基础班-淘宝-目录.txt
卷 TOSHIBA EXT 的文件夹 PATH 列表卷序列号为 AE86-8E8DF:.│ python基础班-淘宝-目录.txt│ ├─1-1 Linux基础│ ├─01-课程简介│ │ 01-课程 ...
- mysql 操作sql语句 操作数据表
#2. 操作文件 先切换到文件夹下:use db1 查看当前所在的数据库 mysql> select database(); +------------+ | database() | +--- ...
- python 面向对象 新式类和经典类
# 经典类写法 # schoolMember.__init__(self, name, age, sex) # 新式类写法 super(Teather, self).__init__(name, ag ...
- laravel教程入门笔记
安装laravel框架 1.安装命令 composer create-project --prefer-dist laravel/laravel ytkah ytkah表示文件夹名,如果不写的话自动会 ...
- 怎样解决VMware虚拟机无法连接外网问题
安装上虚拟机之后,再安装上linux之后,有时会出现ping不通物理机的ip和任何外网包括网关的ip的问题.虚拟机的网卡是桥接状态.下面就让我为大家演示下一下,怎么让虚拟机重新ping通物理机. 工具 ...
- [vue]vue双向绑定$on $emit sync-模态框
双向绑定实现($on $emit) 关于父子之间数据更新同步, 如果单向绑定, 子修改了,父却没有修改, 这种一般不符合规范 正常更新数据的套路是: 1. 子通知父更新数据 2. 子自动刷新获取最新数 ...