MFC实现守护进程,包括开机自启动、进程单例、进程查询、进程等待、重启进程、关闭进程

在Windows平台上实现一个守护进程,由于与系统有关,所有使用MFC来实现是最合适的,被守护的进程则不限语言。废话不多,直接开整。

目录

[1. 开机自启动](#1. 开机自启动)

[2. 进程单例](#2. 进程单例)

[3. 进程查询](#3. 进程查询)

[4. 进程等待](#4. 进程等待)

[5. 重启进程](#5. 重启进程)

[6. 关闭进程](#6. 关闭进程)

7、最后的最后


1. 开机自启动

守护进程自然要开机自启动。

cpp 复制代码
//设置自身开机启动
BOOL SetSelfStart()
{
	//获取程序完整名称
	char pName[MAX_PATH] = { 0 };
	GetModuleFileNameA(NULL, pName, MAX_PATH);

	//在注册表中写入启动信息
	HKEY hKey = NULL;
	LONG lRet = NULL;
	lRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, SELFSTART_REGEDIT_PATH, 0, KEY_ALL_ACCESS, &hKey);

	//判断是否成功
	if (lRet != ERROR_SUCCESS)
	{
		return FALSE;
	}

	lRet = RegSetValueExA(hKey, "w10_daemon", 0, REG_SZ, (const unsigned char*)pName, strlen(pName) + sizeof(char));

	//判断是否成功
	if (lRet != ERROR_SUCCESS)
	{
		return FALSE;
	}

	//关闭注册表
	RegCloseKey(hKey);
	return TRUE;
}

2. 进程单例

也就是防止软件被多次启动,在需要长时间无人值守运行的软件中,不管守护进程或者被守护进程都不希望软件启动多次。

cpp 复制代码
BOOL InitInstance()
{
	LPCWSTR pszExeName = L"GuardApplication";        //    使用软件自身的名称
	// 用应用程序名创建信号量
	HANDLE hSem = CreateSemaphore(NULL, 1, 1, pszExeName);

	// 信号量已存在?
	// 信号量存在,则程序已有一个实例运行
	if (GetLastError() == ERROR_ALREADY_EXISTS)
	{
		// 关闭信号量句柄
		CloseHandle(hSem);

		return FALSE;

		// 寻找先前实例的主窗口
		HWND hWndPrevious = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
		while (::IsWindow(hWndPrevious))
		{
			// 检查窗口是否有预设的标记?
			// 有,则是我们寻找的主窗
			if (::GetProp(hWndPrevious, pszExeName))
			{
				// 主窗口已最小化,则恢复其大小
				if (::IsIconic(hWndPrevious))
					::ShowWindow(hWndPrevious, SW_RESTORE);
				// 将主窗激活
				::SetForegroundWindow(hWndPrevious);
				// 将主窗的对话框激活
				::SetForegroundWindow(::GetLastActivePopup(hWndPrevious));
				// 退出本实例
				return FALSE;
			}

			// 继续寻找下一个窗口
			hWndPrevious = ::GetWindow(hWndPrevious, GW_HWNDNEXT);
		}

		// 前一实例已存在,但找不到其主窗
		// 可能出错了
		// 退出本实例
		return FALSE;
	}

	return TRUE;
}

3. 进程查询

守护进程,自然需要找到被守护的进程id等信息。

cpp 复制代码
BOOL IsExistProcess(CONST WCHAR* szProcessName, DWORD& ProcessID)
{
	PROCESSENTRY32 processEntry32;
	HANDLE toolHelp32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (((int)toolHelp32Snapshot) != -1)
	{
		processEntry32.dwSize = sizeof(processEntry32);
		if (Process32First(toolHelp32Snapshot, &processEntry32))
		{
			do
			{
				if (wcscmp(szProcessName, processEntry32.szExeFile) == 0)
				{
					ProcessID = processEntry32.th32ProcessID;
					return TRUE;
				}
			} while (Process32Next(toolHelp32Snapshot, &processEntry32));
        }
		CloseHandle(toolHelp32Snapshot);
	}

	return FALSE;
}

4. 进程等待

查寻到进程号之后,最好的办法就是等待它退出,而不是定时重复查询。

cpp 复制代码
HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, processEntry32.th32ProcessID);
if (hProcess != NULL) {
	WaitForSingleObject(hProcess, INFINITE);
	CloseHandle(hProcess);
}

5. 重启进程

被守护的进程消失了怎么办?当然是重启该进程喽。

cpp 复制代码
WCHAR* pCmd = L"cmd /c D:\\test\\abcd.exe";

STARTUPINFOW si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW;

//进程对象
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));

//创建子进程,判断是否执行成功
if (!CreateProcessW(NULL, pCmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
	cout << "守护进程启动失败,程序即将退出" << endl;
	return 0;
}

// 等待进程启动
WaitForInputIdle(pi.hProcess, 10000);

// 获取进程窗口句柄
HWND hWnd = FindWindow(NULL, PROCCESS_NAME);
if (hWnd)
{
	// 将进程窗口置顶
	SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
	// 给予焦点
	SetForegroundWindow(hWnd);
}

6. 关闭进程

为什么还要关闭进程呢?当然是需要正常关闭其他进程的时候去做了,比如:被守护的进程不想被守护了,自然需要先杀掉守护进程,再然后自杀。

cpp 复制代码
//利用查找到的进程ID,打开进程:
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processEntry32.th32ProcessID);

//关闭进程
BOOL bRet = TerminateProcess(hProcess, 0);

CloseHandle(hProcess);

7、最后的最后

当然是附上守护进程软件的源码链接了,开源就要彻底,你都看到这了,还不给我点个赞,加个关注吗?就算白嫖也要自觉一点,不是吗?当然能给我打个赏我就万分感谢了!

这是下载链接

相关推荐
oioihoii4 分钟前
C++共享内存小白入门指南
java·c++·算法
布茹 ei ai6 分钟前
QtWeatherApp - 简单天气预报软件(C++ Qt6)(附源码)
开发语言·c++·qt·开源·开源项目·天气预报
Bruce_kaizy6 分钟前
c++图论————图的基本与遍历
c++·算法·图论
Zmm147258369_8 分钟前
好用的PC耐力板机构
c++
Code Slacker36 分钟前
LeetCode Hot100 —— 普通数组(面试纯背版)(五)
数据结构·c++·算法·leetcode·面试
秦苒&1 小时前
【C语言】详解数据类型和变量(一):数据类型介绍、 signed和unsigned、数据类型的取值范围、变量、强制类型转换
c语言·开发语言·c++·c#
智者知已应修善业1 小时前
【删除有序数组中的重复项 II之O(N)算法】2024-1-31
c语言·c++·经验分享·笔记·算法
爱装代码的小瓶子1 小时前
【c++进阶】C++11新特性:一切皆可{}初始化
开发语言·c++·visual studio
xiaoye-duck2 小时前
吃透C++类和对象(中):构造函数与析构函数深度解析
c++
AA陈超2 小时前
Lyra Starter Game 中 GameFeature 类(如 ShooterCore)的加载流程
c++·笔记·学习·ue5·虚幻引擎