转载: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();
}
}

守护进程Demo

VC++使用服务做守护进程的示例(转载)的更多相关文章

  1. Supervisor 为服务创建守护进程

    今天需要再服务上部署一个.net 方面的项目:当时开启服务的命令只能在前台执行:使用nohub CMD &等放在后台开启服务都会宕机:所以搜寻了Supervisor 这个解决办法,为服务创建守 ...

  2. Linux控制服务和守护进程

    目录 控制服务和守护进程 1.systemd 1.1.systemd简介 1.2.systemd的新特性 1.3.systemd的核心概念Unit 2.使用systemctl管理服务 控制服务和守护进 ...

  3. Linux_控制服务与守护进程

    一.systemd 1.systemd简介 1️⃣:systemd是用户空间的第一个应用程序,即/sbin/init 2️⃣:init程序的类型: SysV风格:init(centos5),实现系统初 ...

  4. Windows守护进程简单示例

    转载: https://blog.csdn.net/kikaylee/article/details/51395360 /* @描述:一个简单的Windows守护进程的例子(C++版本) @作者:ki ...

  5. PHP实现多进程并行操作,可做守护进程(转,备用)

    <?php /** * 入口函数 * 将此文件保存为 ProcessOpera.php * 在terminal中运行 /usr/local/php/bin/php ProcessOpera.ph ...

  6. java实现服务端守护进程来监听客户端通过上传json文件写数据到hbase中

    1.项目介绍: 由于大数据部门涉及到其他部门将数据传到数据中心,大部分公司采用的方式是用json文件的方式传输,因此就需要编写服务端和客户端的小程序了.而我主要实现服务端的代码,也有相应的客户端的测试 ...

  7. linux分享一:进程全攻略--守护进程(服务)

    概括: 进程是程序的运行实例.进程对应一个唯一的进程PID, 统一程序的多个实例可以同时运行,他们的pid互不相同. 进程一般分为交互进程.批处理进程和守护进程(daemons)三类 一:什么是守护进 ...

  8. 深入理解Linux操作系统守护进程的意义

    Linux服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程(daemons)来执行的.守护进程 ...

  9. 守护进程与Supervisor

    博客链接:http://www.cnblogs.com/zhenghongxin/p/8676565.html 消息队列处理后台任务带来的问题 在系统稍微大些的时候,我们经常会用到消息队列(实现的方式 ...

随机推荐

  1. Python:lambda表达式(匿名函数)

    lambda表达式: 通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数. 当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便. 在Python中 ...

  2. 2018/03/27 每日一个Linux命令 之 cron

    Cron 用于配置定时任务. -- 环境为 Ubuntu16-04 -- 先说说怎么配置一个简单的定时任务.直观的可以看到效果. 之前在网上查找资料,对Shell编程不熟悉的实在是很头疼,走了不少弯路 ...

  3. VMware上安装VMware tools

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/walkerkalr/article/details/34896407  VMware上安装VMw ...

  4. HTML5-CSS3-JavaScript(4)

    CSS3中 变形与动画相关属性 CSS3在原来的基础上新增了变形和动画相关属性,通过这些属性可以实现以前需要大段JavaScript才能实现的功能.CSS3的变形功能可以对HTML组件执行位移.旋转. ...

  5. 搭建基于HTTP协议内网yum仓库

    目录 1. 前言 2. 把rpm包下载到本地 3. 配置nginx对外提供服务 4. 配置本地repo文件 5. 生成repodata信息 6. 检查及使用 7. 对管理机器上的仓库进行更新 参考资料 ...

  6. 如何快速获取ListView的打气筒对象

    简单的方式有三种: @Override public View getView(int position, View convertView, ViewGroup parent) { View vie ...

  7. 7.4 Models -- Pushing Records into the Store

    一.概述 1. store是作为一个所有records的缓存,这些records已经被你的应用程序加载.在你的app中如果你的路由或者一个controller请求一条record,如果它在缓存中这个s ...

  8. SQL工具类

    package com.ebizwindow.crm.utils; import java.util.List; import com.ebizwindow.crm.constants.SqlCons ...

  9. Python Socket编程基础篇

    Socket网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. ...

  10. EditPlus 5.1.2066 中文版(1月30日修正)

    之前有一些网友反馈汉化版的 EditPlus 中翻页键无法正常工作.经过调查,发现是翻译工具的问题. 因此,我用新的工具重新翻译了 EditPlus.翻页键在新中文版中应该可以正常工作了. 有需要的网 ...