1 守护进程

1.1 需求分析

我有三个程序需要不断运行,有可能出现某些未知的原因而宕掉,需要本守护程序来进行守护,发现它运行不管,死掉就重启它,并且服务器开机就启动。

1.2 使用方法

将该程序与需要守护的程序放在同一目录。修改以下几处

  • 守护的程序的绝对路径 twkWindowName_DownloadWget
  • 定义守护进程名称 PROCCESS_NAME_DOWMLOADWGET
  • 需要守护的程序所在的路径 PROGRAMEPATH

开发环境:

  • Windows10专业版
  • Visual Studio 2017 Enterprise

1.3 实现代码

/*****************************************************************************
Author:                唐维康
Date:                  2020年10月05日
Code:                  UNICODE
description:       守护进程:查看下载+转换+维护三个程序是否因为某种原因死掉,如果死掉就重启它
开发环境:          Visual Studio 2017 Enterprise 和 Windows10专业版使用说明:          PROCCESS_NAME_DOWMLOADWGET守护进程名称根据需要守护的进程修改;twkWindowName_DownloadWget 是需要守护的程序的绝对路径PROCCESS_NAME_MAINTENANCEPROCEDURES是需要守护的程序所在的路径 一般情况和本程序在同一目录
************************************************************************/#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <io.h>
#include <iostream>
#include <tchar.h>//参考网站
//https://blog.csdn.net/jelly_chen_zo/article/details/21546245?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242
//https://blog.csdn.net/u013408061/article/details/53314327//使用这个 TEXT 宏就可以使得程序都可以正常使用
//TEXT使路径成为Unicode字符串 必须为LPCTSTR格式,强制类型转换不行
//下面三个定义为是需要守护的程序的绝对路径
LPCTSTR twkWindowName_DownloadWget = TEXT("D:\\Desktop\\Monitor_TangWeiKang\\UpgradedMonitoringMachine_TangWeiKang\\RecordingSeparation\\code\\MP3Conversion\\Daemon\\Test01.exe");
LPCTSTR twkWindowName_MP3Conversion = TEXT("D:\\Desktop\\Monitor_TangWeiKang\\UpgradedMonitoringMachine_TangWeiKang\\RecordingSeparation\\code\\MP3Conversion\\Daemon\\Test02.exe");
LPCTSTR twkWindowName_MaintenanceProcedures = TEXT("D:\\Desktop\\Monitor_TangWeiKang\\UpgradedMonitoringMachine_TangWeiKang\\RecordingSeparation\\code\\MP3Conversion\\Daemon\\Test03.exe");//LPCTSTR szAppWindowName = L"D:\\Desktop\\Monitor_TangWeiKang\\UpgradedMonitoringMachine_TangWeiKang\\RecordingSeparation\\code\\MP3Conversion\\Daemon\\Test01.exe";
using namespace std;//隐藏DOS黑窗口
//#pragma comment(linker,"/subsystem:\"windows\"  /entry:\"mainCRTStartup\"" )//定义路径最大程度
#define MAX_PATH_NUM 4096//定义守护进程名称
#define PROCCESS_NAME_DOWMLOADWGET "Test01.exe"
#define PROCCESS_NAME_MP3CONVERSION "Test02.exe"
#define PROCCESS_NAME_MAINTENANCEPROCEDURES "Test03.exe"
//PROGRAMEPATH 是需要守护的程序所在的路径 一般情况和本程序在同一目录
#define PROGRAMEPATH "D:\\Desktop\\Monitor_TangWeiKang\\UpgradedMonitoringMachine_TangWeiKang\\RecordingSeparation\\code\\MP3Conversion\\Daemon"//定义写入的注册表路径
#define SELFSTART_REGEDIT_PATH "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\"BOOL SetSelfStart();int main()
{Notepad获得守护的进程的句柄HWND handle = FindWindow(NULL, szAppWindowName);HWND handle = FindWindow(NULL, (LPCTSTR)"Notepad");//HWND handle = FindWindow(NULL, szAppWindowName);//if (handle != NULL)//{// /*MessageBox(NULL, TEXT("Application is already running"), szAppClassName, MB_ICONERROR);//   ExitProcess(1);*/// cout << "该程序已经在运行了!" << endl;//    continue;//}//else//{// cout << "没有存在" << endl;//}//获取程序完整名称char pName[MAX_PATH_NUM] = { 0 };GetModuleFileNameA(NULL, pName, MAX_PATH_NUM);//twk测试/*cout << "***************" << endl;cout << pName << endl;cout << "***************" << endl;*///设置程序开机自启动if (!SetSelfStart()){cout << "守护进程开机自启动失败" << endl;return -1;}else{cout << "守护进程开机自启动成功" << endl;}STARTUPINFOA si;// 该结构用于指定新进程的主窗口特性//进程对象PROCESS_INFORMATION pi[3];//初始化ZeroMemory(&si, sizeof(si));si.cb = sizeof(si);ZeroMemory(&pi, sizeof(pi));//进程相关信息(句柄,标识)//获取当前程序的路径 不用GetCurrentDirectoryA函数获取是因为开机读取了其它路径//开机读取的路径是 pPath=C:\Windows\system32\test02.exechar pPath_DownloadWget[MAX_PATH_NUM] = { 0 };//GetCurrentDirectoryA(MAX_PATH_NUM, pPath_DownloadWget);strcat(pPath_DownloadWget, PROGRAMEPATH);char pPath_MP3Conversion[MAX_PATH_NUM] = { 0 };//GetCurrentDirectoryA(MAX_PATH_NUM, pPath_MP3Conversion);strcat(pPath_MP3Conversion, PROGRAMEPATH);char pPath_MaintenanceProcedures[MAX_PATH_NUM] = { 0 };//GetCurrentDirectoryA(MAX_PATH_NUM, pPath_MaintenanceProcedures);strcat(pPath_MaintenanceProcedures, PROGRAMEPATH);//拼接需要守护的程序strcat(pPath_DownloadWget, "\\");strcat(pPath_DownloadWget, PROCCESS_NAME_DOWMLOADWGET);strcat(pPath_MP3Conversion, "\\");strcat(pPath_MP3Conversion, PROCCESS_NAME_MP3CONVERSION);strcat(pPath_MaintenanceProcedures, "\\");strcat(pPath_MaintenanceProcedures, PROCCESS_NAME_MAINTENANCEPROCEDURES);//cout << " pPath_MaintenanceProcedures="<<pPath_MaintenanceProcedures << endl;//构造cmd执行守护进程的字符串char pCmd_DownloadWget[MAX_PATH_NUM] = { 0 };strcat(pCmd_DownloadWget,"cmd /c ");strcat(pCmd_DownloadWget, pPath_DownloadWget);char pCmd_MP3Conversion[MAX_PATH_NUM] = { 0 };strcat(pCmd_MP3Conversion, "cmd /c ");strcat(pCmd_MP3Conversion, pPath_MP3Conversion);char pCmd_MaintenanceProcedures[MAX_PATH_NUM] = { 0 };strcat(pCmd_MaintenanceProcedures, "cmd /c ");strcat(pCmd_MaintenanceProcedures, pPath_MaintenanceProcedures);//twk测试//cout << "pPath_DownloadWget=" << pPath_DownloadWget << endl;//char twkWindowName[MAX_PATH_NUM] = { 0 };//strcat(twkWindowName, pPath_DownloadWget);//LPCTSTR *twkWindowName = (LPCTSTR *)malloc(4096 * sizeof(LPCTSTR));//sprintf(twkWindowName,"%s", (LPCTSTR)pPath_DownloadWget);//cout << "twkWindowName=" << twkWindowName.c_str() << endl;//cout << "szAppWindowName"<<szAppWindowName << endl;//无限循环,监视守护进程do {//检查守护程序是否存在if ((_access(pPath_DownloadWget, 0) != -1)|| (_access(pPath_MP3Conversion, 0) != -1)|| (_access(pPath_MaintenanceProcedures, 0) != -1)){//获得守护的进程的句柄//HWND handle = FindWindow(NULL, szAppWindowName);//HWND handle = FindWindow(NULL, (LPCTSTR)"Notepad");HWND handle_DownloadWget = FindWindow(NULL, twkWindowName_DownloadWget);//HWND handle = FindWindow(NULL, (LPCWSTR)pPath_DownloadWget);if (handle_DownloadWget != NULL){/*MessageBox(NULL, TEXT("Application is already running"), szAppClassName, MB_ICONERROR);ExitProcess(1);*/cout << "守护的程序DownloadWget正在运行!" << endl;}else{if (!CreateProcessA(NULL, pCmd_DownloadWget, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi[0])){cout << "守护进程DownloadWget启动失败,程序即将退出" << endl;return -1;}}HWND handle_MP3Conversion = FindWindow(NULL, twkWindowName_MP3Conversion);//HWND handle = FindWindow(NULL, (LPCWSTR)pPath_DownloadWget);if (handle_MP3Conversion != NULL){/*MessageBox(NULL, TEXT("Application is already running"), szAppClassName, MB_ICONERROR);ExitProcess(1);*/cout << "守护的程序MP3Conversion正在运行!" << endl;}else{if (!CreateProcessA(NULL, pCmd_MP3Conversion, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi[0])){cout << "守护进程MP3Conversion启动失败,程序即将退出" << endl;return -1;}}HWND handle_MaintenanceProcedures = FindWindow(NULL, twkWindowName_MaintenanceProcedures);//HWND handle = FindWindow(NULL, (LPCWSTR)pPath_DownloadWget);if (handle_MaintenanceProcedures != NULL){/*MessageBox(NULL, TEXT("Application is already running"), szAppClassName, MB_ICONERROR);ExitProcess(1);*/cout << "守护的程序MaintenanceProcedures正在运行!" << endl;}else{if (!CreateProcessA(NULL, pCmd_MaintenanceProcedures, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi[0])){cout << "守护进程MaintenanceProcedures启动失败,程序即将退出" << endl;//continue;return -1;}}for (int i = 0; i < 3; i++){//启动成功,获取进程的IDcout << "守护进程成功,ID:" << pi[i].dwProcessId << endl;//无限等待子进程退出WaitForSingleObject(pi[i].hProcess, INFINITE);cout << "守护进程退出了。。。" << endl;//关闭进程和句柄CloseHandle(pi[i].hProcess);CloseHandle(pi[i].hThread);}}else{cout << "守护程序不存在" << endl;}//睡一下,重启Sleep(2000);//int a;//a = CreateProcessA(NULL, (LPSTR)"Test01.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi[0]);//a = CreateProcessA(NULL, (LPSTR)"Test02.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi[1]);//a = CreateProcessA(NULL, (LPSTR)"Test03.exe", NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi[2]);// //终止线程for (int i = 0; i < 3; i++){OpenProcess(NULL, true, pi[i].dwProcessId);DWORD fuExitCode;       // 进程的退出码GetExitCodeProcess(pi[i].hProcess, &fuExitCode);   // 获得进程的退出码TerminateProcess(pi[i].hProcess, fuExitCode);        // 终止进程CloseHandle(pi[i].hThread);CloseHandle(pi[i].hProcess);}} while (true);return 0;
}//设置本身开机自启动
BOOL SetSelfStart()
{//获取程序完整名称char pName[MAX_PATH_NUM] = { 0 };GetModuleFileNameA(NULL, pName, MAX_PATH_NUM);//在注册表中写入启动信息HKEY hKey = NULL;LONG lRet = 0;lRet = RegOpenKeyExA(HKEY_CURRENT_USER, SELFSTART_REGEDIT_PATH, 0, KEY_ALL_ACCESS, &hKey);//判断是否成功if (lRet != ERROR_SUCCESS){return FALSE;}lRet = RegSetValueExA(hKey, "Daemon", 0, REG_SZ, (const unsigned char*)pName, strlen(pName) + sizeof(char));//判断是否成功if (lRet != ERROR_SUCCESS){return FALSE;}//关闭注册表RegCloseKey(hKey);return TRUE;
}// 取消开机自动启动
void cancelAutoStart()
{HKEY hKey;string strRegPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";//1、找到系统的启动项  if (RegOpenKeyEx(HKEY_CURRENT_USER, (LPCTSTR)strRegPath.c_str(), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS){//2、删除值RegDeleteValue(hKey, (LPCTSTR)"GISRestart");//3、关闭注册表RegCloseKey(hKey);}
}

1.4 结果显示

我用了三个程序来测试,Test01.exe Test02.exe Test03.exe 都是循环打印该进程PID,并且与守护程序放在了同一目录。

开机启动测试

界面显示系统开机程序也跟随开机。

重启程序测试

当守护程序宕掉,2秒后重启。

存在检查

如果有一个守护的程序已经运行了,就不需要管。

我们手动运行Test01.exe。界面显示Test01.exe跳过,它已经存在了。

windows下的守护进程C++相关推荐

  1. windows下创建守护进程A和B 互相监视 挂掉拉起

    在windows下创建守护进程A和B ,在其中一个挂掉以后,另一个会把挂掉的拉起来. 下面展示一些 内联代码片. 这里只列出了A的代码,B和A类似. #include<iostream> ...

  2. 写一个Windows上的守护进程(4)日志其余

    写一个Windows上的守护进程(4)日志其余 这次把和日志相关的其他东西一并说了. 一.vaformat C++日志接口通常有两种形式:流输入形式,printf形式. 我采用printf形式,因为流 ...

  3. windows下 解决PHP-CGI 进程崩溃502

    PHP是世界上最好的语言,但需要PHP解析器:Apache+php,需要通过mod_php.so和php相连:nginx+php 需要转发给 cgi程序 关于FastCGI: 全称 FastCGI P ...

  4. 写一个Windows上的守护进程(7)捕获异常并生成dump

    写一个Windows上的守护进程(7)捕获异常并生成dump 参考文章: (1)写一个Windows上的守护进程(7)捕获异常并生成dump (2)https://www.cnblogs.com/mk ...

  5. arch下aria2c守护进程等配置小结

    arch下aria2c守护进程等配置小结 前言 aria2c是个好东西,可以把他简单理解为是下载管理器的后端,配合一些前端程序,比如ariaNG,可以管理其下载的各类东西,再配合百度云导出真实下载地址 ...

  6. 浅显理解*nix下的守护进程机制及fork函数

    最近空闲时间重新仔细看了一下memcached的使用说明文档,硬着头皮看了一点源码,有时候看到一些晦涩的c函数感觉实在恍惚只能跳过.不过也不算是全无收获,终于LZ还敢再看c语言,终于LZ又看起了c语言 ...

  7. windows下查看当前进程,杀掉进程等

    虽然我们平时学习最多的是linux命令,但是平时开发,更多的却是在windows下,而cmd命令也是我们经常需要用到的.cmd命令和linux命令有相同也有不同之处.这里记录一下windows下,如何 ...

  8. 嵌入式linux系统下简单守护进程(daemon)的编写

    最近公司项目需要,需要在我们的嵌入式linux设备中创建一个守护进程,用于保护系统中的主进程,防止某些不可预期的意外导致主进程异常结束后,系统完全宕机没有任何反应,破坏用户体验感.但是,查阅诸多资料之 ...

  9. linux下daemon守护进程的实现(以nginx代码为例)

    ngx_int_t ngx_daemon(ngx_log_t *log) {int fd;// 让init进程成为新产生进程的父进程:// 调用fork函数创建子进程后,使父进程立即退出.这样,产生的 ...

最新文章

  1. c++采集声卡输出_耳上明珠 | 魅族双 C 耳机 — EP2C
  2. python3 删除 文件 文件夹
  3. gin自定义路由日志的格式
  4. Windows Phone APP中禁用截图
  5. fantouch os Android 7,Funtouch OS 3.1 with Android 7.1升级计划
  6. 反思赚钱:一定要动脑子 一定找发财点
  7. Javaone 2013评论
  8. 2821: 作诗(Poetize)
  9. 百度、阿里等大厂面试技巧总结,Java工程师必看!
  10. 连锁百货企业数据系统整理解决方案
  11. jQuery JCrop插件的一个问题
  12. CAD2020操作手册
  13. Android CallStack
  14. 学习笔记(27):玩转Python-Python3基础入门-案例-快递价格计算器(2)
  15. 计算机本地连接无internet访问权限,ipv4连接无internet访问权限怎么解决
  16. 证明三角形中cosA^2+cosB^2+cosC^2=1-2cosAcosBcosC
  17. 设置360浏览器的背景为护眼模式(浅豆绿色)
  18. day 1-requests基础用法和网页基础学习总结
  19. Codechef June Challenge 2020 简要题解
  20. Mysql 常用函数(20)- ceiling 函数

热门文章

  1. 谁拿了最多奖学金pascal程序
  2. 目前我国家庭计算机用户接入因特网的下述,目前我国家庭计算机用户接入因特网的下述几种方法中,速度最快的是________ 。...
  3. val_loss突然变很大_程干朋说网络营销之网站收录突然降低怎么办?
  4. python怎样入门_python怎么入门啊?
  5. 【学习笔记】【Design idea】一、Java异常的设计思想、性能相关、笔记
  6. python简说(二十二)写日志
  7. 企业项目开发--企业中的项目架构以及多环境分配(2)
  8. HDU 5527:Too Rich(DFS+贪心)***
  9. getElementById 和 getElementByName的区别
  10. iOS NSUserDefaults 简介 NSUserDefaults 存储自定义对象