转载: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. YARN Architecture

    The fundamental idea of YARN is to split up the functionalities of resource management and job sched ...

  2. iOS多线程编程之GCD的基本使用(转载)

    一.主队列介绍 主队列:是和主线程相关联的队列,主队列是GCD自带的一种特殊的串行队列,放在主队列中得任务,都会放到主线程中执行. 提示:如果把任务放到主队列中进行处理,那么不论处理函数是异步的还是同 ...

  3. 网站优化不等于搜索引擎优化SEO

    对于SEO相信搞网络营销的人基本上都知道这个名词,英文全称为search engine optimization,中文一般叫搜索引擎优化,也有的叫搜索引擎定位(Search Engine Positi ...

  4. dedecms获取当前文章所在栏目URL

    我们知道dedecms有一个面包屑导航的调用函数,{dede:field name='position'/},这个样式是固定的,有时要个性化一些的话需要修改很多地方,那么织梦cms有没其他方法获取当前 ...

  5. MyEclipse10.0 注册破解步骤

    MyEclipse 10.0破解 激活(java编写,适用于装有java环境的各种操作系统,Windows,Linux,MacOS) =====[方法一]=====[第一步]:输入任意用户名[第二步] ...

  6. 简述ASP.NET的页面运行机制

    在深入学习ASP.NET之前,首先需要先了解一下ASP.NET的页面运行机制: 浏览以下内容需要对ASP.NET管道有一定的了解,附上很不错的几个链接: 选择HttpHandler还是HttpModu ...

  7. Gcc ------ gcc的使用简介与命令行参数说明

    gcc的使用简介与命令行参数说明 2011年06月19日 20:29:00 阅读数:10221 2011-06-19 wcdj 参考:<GNU gcc嵌入式系统开发 作者:董文军> (一) ...

  8. col-md-*和col-sm-*

    屏幕大于(≥992px) ,使用col-md-* 而不是col-sm-*如果屏幕大于(≥768px),小雨<=992px,使用col-sm-* 而不是col-md-*

  9. Word Add-in 函数调用顺序

    这个图表明的函数的调用顺序,主要代码如下: // MyAddin.cpp : Implementation of DLL Exports. // Note: Proxy/Stub Informatio ...

  10. UNDFTD x Nike Air Max 97 OG Black

    The UNDFTD x Nike Air Max 97 OG Black is releasing way sooner than anticipated. This collaborative r ...