14 MFC多进程

news2024/9/28 17:35:15

文章目录

  • 创建进程
    • win32子进程内容
    • 创建进程传递参数
    • 关闭进程
    • 通过配置文件读取
    • 全部代码
  • 打开进程
  • 便利进程

创建进程

分别创建MFC应用程序和Win32应用程序

MFC应用程序界面设置
在这里插入图片描述

win32子进程内容

#include <Windows.h>
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdshow)
{

	MessageBox(NULL, lpCmdLine, L"提示", MB_OK);
	return 0;
}

将*.exe放入到主线程的Debug中
在这里插入图片描述

创建进程传递参数

void CParentDlg::OnBnClickedBtnStart()
{

	for (int i = 0; i < 10; i++)
	{
		//创建子进程
		//第二个参数不能传递常量,而应该传递一块内存
			/*启动顺序:
				1.父进程所在目录
				2.Windows系统目录
					TCHAR szPath[MAX_PATH];
					GetSystemDirectory(szPath,MAX_PATH);//获取系统目录
				3.Windows目录
				4.环境变量指定目录
			*/

		wchar_t szExePath[MAX_PATH] = L"sub.exe";

		wsprintf(szExePath, L"sub.exe %d-%d", i*100, i*100 + 99);

		//第三个参数:进程安全属性填写为NULL,表示为默认安全属性
		SECURITY_ATTRIBUTES sa;
		sa.nLength = sizeof(SECURITY_ATTRIBUTES);
		sa.lpSecurityDescriptor = NULL;//表示默认
		sa.bInheritHandle = TRUE;
		//第四个参数:线程安全属性
		//第五个参数:指示新进程是否从调用进程继承句柄
		//第六个参数:创建标记 0代表默认
		//第七个参数:环境变量
		//第八个参数:工作目录
		//第九个参数:启动信息
		STARTUPINFO si = { sizeof(STARTUPINFO) };
		//si.cb = sizeof(STARTUPINFO);
		//第十个参数进程信息
		PROCESS_INFORMATION pi = { 0 };

		if (TRUE == CreateProcess(NULL, szExePath, &sa, NULL, TRUE, 0, NULL, NULL, &si, &pi))
		{
			m_hSub[i] = pi.hProcess;//获取进程句柄
		}
	}

}

在这里插入图片描述

关闭进程

void CParentDlg::OnBnClickedBtnStop()
{
	for (int i = 0; i < 10; i++)
	{
		if (m_hSub[i] != NULL)
		{
			//等待信号改变
			//WaitForSingleObject(m_hSub[i], INFINITE);

			//引用计数
			CloseHandle(m_hSub[i]);//减小引用技术
			
			MessageBox(L"程序已关闭", L"提示",MB_OK);

			//强制关闭一个进程
			TerminateProcess(m_hSub[i], 0);//关闭代码,退出
		}
	}
}

通过配置文件读取

配置文件在这里插入图片描述

获取配置文件

bool CParentDlg::InitEnvironment()
{
	//读取配置文件
	//address of section name
	//address of key name
	//return value if key name is not found
	//address of initialization filename
	m_subProcessNum=GetPrivateProfileInt(L"Base",L"subProcessNum",0,L"D:\\MFCProject\\Parent\\Debug\\Parent.ini");
	
	if (m_subProcessNum != 0)
	{
		m_hSub = new HANDLE[m_subProcessNum];
	}
	return TRUE;
}

点击按钮

void CParentDlg::OnBnClickedBtnStart()
{
	InitEnvironment();//初始化环境
	for (int i = 0; i < CParentDlg::m_subProcessNum; i++)
	{
		//创建子进程
		//第二个参数不能传递常量,而应该传递一块内存
			/*启动顺序:
				1.父进程所在目录
				2.Windows系统目录
					TCHAR szPath[MAX_PATH];
					GetSystemDirectory(szPath,MAX_PATH);//获取系统目录
				3.Windows目录
				4.环境变量指定目录
			*/

		wchar_t szExePath[MAX_PATH] = L"sub.exe";

		wsprintf(szExePath, L"sub.exe %d-%d", i*100, i*100 + 99);

		//第三个参数:进程安全属性填写为NULL,表示为默认安全属性
		SECURITY_ATTRIBUTES sa;
		sa.nLength = sizeof(SECURITY_ATTRIBUTES);
		sa.lpSecurityDescriptor = NULL;//表示默认
		sa.bInheritHandle = TRUE;
		//第四个参数:线程安全属性
		//第五个参数:指示新进程是否从调用进程继承句柄
		//第六个参数:创建标记 0代表默认
		//第七个参数:环境变量
		//第八个参数:工作目录
		//第九个参数:启动信息
		STARTUPINFO si = { sizeof(STARTUPINFO) };
		//si.cb = sizeof(STARTUPINFO);
		//第十个参数进程信息
		PROCESS_INFORMATION pi = { 0 };

		if (TRUE == CreateProcess(NULL, szExePath, &sa, NULL, TRUE, 0, NULL, NULL, &si, &pi))
		{
			m_hSub[i] = pi.hProcess;//获取进程句柄
		}
	}

	//等待信号的变化
	//WaitForMultipleObjects(m_subProcessNum, CParentDlg::m_hSub,TRUE, INFINITE);
}

全部代码

// ParentDlg.cpp: 实现文件
//

#include "pch.h"
#include "framework.h"
#include "Parent.h"
#include "ParentDlg.h"
#include "afxdialogex.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CParentDlg 对话框



CParentDlg::CParentDlg(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_PARENT_DIALOG, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	m_subProcessNum = 0;
	m_hSub = NULL;
}

CParentDlg::~CParentDlg()
{
	if (m_hSub != NULL)
	{
		delete[] m_hSub;
		m_hSub = NULL;
	}
}

void CParentDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CParentDlg, CDialogEx)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_BTN_START, &CParentDlg::OnBnClickedBtnStart)
	ON_BN_CLICKED(IDC_BTN_STOP, &CParentDlg::OnBnClickedBtnStop)
END_MESSAGE_MAP()


// CParentDlg 消息处理程序

BOOL CParentDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CParentDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作区矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialogEx::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标
//显示。
HCURSOR CParentDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}



void CParentDlg::OnBnClickedBtnStart()
{
	InitEnvironment();//初始化环境
	for (int i = 0; i < CParentDlg::m_subProcessNum; i++)
	{
		//创建子进程
		//第二个参数不能传递常量,而应该传递一块内存
			/*启动顺序:
				1.父进程所在目录
				2.Windows系统目录
					TCHAR szPath[MAX_PATH];
					GetSystemDirectory(szPath,MAX_PATH);//获取系统目录
				3.Windows目录
				4.环境变量指定目录
			*/

		wchar_t szExePath[MAX_PATH] = L"sub.exe";

		wsprintf(szExePath, L"sub.exe %d-%d", i*100, i*100 + 99);

		//第三个参数:进程安全属性填写为NULL,表示为默认安全属性
		SECURITY_ATTRIBUTES sa;
		sa.nLength = sizeof(SECURITY_ATTRIBUTES);
		sa.lpSecurityDescriptor = NULL;//表示默认
		sa.bInheritHandle = TRUE;
		//第四个参数:线程安全属性
		//第五个参数:指示新进程是否从调用进程继承句柄
		//第六个参数:创建标记 0代表默认
		//第七个参数:环境变量
		//第八个参数:工作目录
		//第九个参数:启动信息
		STARTUPINFO si = { sizeof(STARTUPINFO) };
		//si.cb = sizeof(STARTUPINFO);
		//第十个参数进程信息
		PROCESS_INFORMATION pi = { 0 };

		if (TRUE == CreateProcess(NULL, szExePath, &sa, NULL, TRUE, 0, NULL, NULL, &si, &pi))
		{
			m_hSub[i] = pi.hProcess;//获取进程句柄
		}
	}
	//等待信号的变化
	//WaitForMultipleObjects(m_subProcessNum, CParentDlg::m_hSub,TRUE, INFINITE);
}


void CParentDlg::OnBnClickedBtnStop()
{
	for (int i = 0; i < 10; i++)
	{
		if (m_hSub[i] != NULL)
		{
			//等待信号改变
			//WaitForSingleObject(m_hSub[i], INFINITE);

			//引用计数
			CloseHandle(m_hSub[i]);//减小引用技术
			
			MessageBox(L"程序已关闭", L"提示",MB_OK);

			//强制关闭一个进程
			TerminateProcess(m_hSub[i], 0);//关闭代码,退出

			
			
		}
	}
}

bool CParentDlg::InitEnvironment()
{
	//读取配置文件
	//address of section name
	//address of key name
	//return value if key name is not found
	//address of initialization filename
	m_subProcessNum=GetPrivateProfileInt(L"Base",L"subProcessNum",0,L"D:\\MFCProject\\Parent\\Debug\\Parent.ini");
	
	if (m_subProcessNum != 0)
	{
		m_hSub = new HANDLE[m_subProcessNum];
	}
	return TRUE;
}
// ParentDlg.h: 头文件
//

#pragma once


// CParentDlg 对话框
class CParentDlg : public CDialogEx
{
// 构造
public:
	CParentDlg(CWnd* pParent = nullptr);	// 标准构造函数
	~CParentDlg();
// 对话框数据
#ifdef AFX_DESIGN_TIME
	enum { IDD = IDD_PARENT_DIALOG };
#endif

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);	// DDX/DDV 支持


// 实现
protected:
	HICON m_hIcon;

	// 生成的消息映射函数
	virtual BOOL OnInitDialog();
	afx_msg void OnPaint();
	afx_msg HCURSOR OnQueryDragIcon();
	DECLARE_MESSAGE_MAP()
public:
	HANDLE* m_hSub;
	afx_msg void OnBnClickedBtnStart();
	afx_msg void OnBnClickedBtnStop();
	bool InitEnvironment();
	int m_subProcessNum;
};

打开进程

ui界面
在这里插入图片描述设置关联变量
在这里插入图片描述
在这里插入图片描述获取窗口句柄
在这里插入图片描述

关闭按钮

void COpenDlg::OnBnClickedBtnClose()
{
	UpdateData(TRUE);//刷新 TRUE 代表把界面上显示的数值,更新到关联变量中
	//获得一个窗口名和类型名
	HWND hWnd = ::FindWindow(m_strWindowClass,m_strWindowTitle);
	if (hWnd == NULL)
	{
		MessageBox(L"没有找到");
		return;
	}


	//通过窗口句柄获得进程ID
	DWORD dwPID;
	GetWindowThreadProcessId(hWnd, &dwPID);



	//打开进程
	//第一个参数:访问权限
	//第二个参数:

	HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS,TRUE, dwPID);

	if (hProcess == NULL)
	{
		MessageBox(L"打开进程失败");
		return;
	}

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

}

请添加图片描述

便利进程

请添加图片描述

初始化列表

BOOL CergodicProcessDlg::OnInitDialog()
{
	CDialogEx::OnInitDialog();

	// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	m_list.InsertColumn(0, _T("进程名"), LVCFMT_LEFT, 120);
	m_list.InsertColumn(1, _T("PID"), LVCFMT_LEFT, 100);
	m_list.SetExtendedStyle(LVS_EX_FULLROWSELECT);//扩展样式,显示高亮

	m_list2.InsertColumn(0, _T("模块路径"), LVCFMT_LEFT, 200);
	m_list2.SetExtendedStyle(LVS_EX_FULLROWSELECT);//扩展样式

	EnumProcess();

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

创建进程快照

void CergodicProcessDlg::EnumProcess()
{
	//创建进程快照
	HANDLE hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
	//返回进程列表
	PROCESSENTRY32 pe32{sizeof(PROCESSENTRY32)};//枚举驻留的进程
	BOOL b=Process32First(hSnapshot, &pe32);
	int i = 0;
	while (b)
	{
		m_list.InsertItem(i, pe32.szExeFile);
		CString str;
		str.Format(L"%d", pe32.th32ParentProcessID);
		m_list.SetItemText(i, 1, str);
		b=Process32Next(hSnapshot, &pe32);//获取下一个进程
		i++;
	}
}

创建进程模块

void CergodicProcessDlg::EnumModule(DWORD dwPID)
{
	//创建进程快照
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
	//返回进程列表
	MODULEENTRY32 me32{ sizeof(MODULEENTRY32) };//枚举驻留的进程
	BOOL b = Module32First(hSnapshot, &me32);
	int i = 0;
	while (b)
	{
		m_list2.InsertItem(i, me32.szExePath);
		
		b = Module32Next(hSnapshot, &me32);//获取下一个进程
		i++;
	}
	
}

点击进程获取进程模块

在这里插入图片描述

void CergodicProcessDlg::OnDblclkList1(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	
	int nSel = m_list.GetSelectionMark();//获取选中的

	if (nSel < 0)
		return;
	DWORD dwPID = _wtoi(m_list.GetItemText(nSel, 1));
	m_list2.DeleteAllItems();//删除原来的
	EnumModule(dwPID);
	*pResult = 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/711941.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分享在Linux下使用OSGi.NET插件框架快速实现一个分布式服务集群的方法

在这篇文章我分享了如何使用分层与模块化的方法来设计一个分布式服务集群。这个分布式服务集群是基于DynamicProxy、WCF和OSGi.NET插件框架实现的。我将从设计思路、目标和实现三方面来描述。 1 设计思路 首先&#xff0c;我来说明一下设计思路。我们先来看看目前OSGi.NET插件…

C++中生成二维码-libqrencode

文章目录 前言libqrencode在qt中调用libqrencode其他 前言 二维码的种类很多。本文仅介绍&#xff0c;如何用C生成QR码(QRcode)。通常而言&#xff0c;我们不需要知道QR码的详细结构&#xff0c;如QrCode的结构原理与实战 | 张展鹏的博客。我们只需要&#xff0c;可以将文本转…

Python——— 字符串

&#xff08;一&#xff09;字符串 字符串是 Python 中最常用的数据类型。我们可以使用引号 ( 或 " ) 来创建字符串。顾名思义&#xff0c;羊肉串是由羊肉做成的串&#xff0c;而字符串就是由字符组成的。 字符串的本质是&#xff1a;字符序列。 2 Python 不支持单字符…

Kafka 小结

Kafka 是由 Linkedin 开发并开源的分布式消息系统&#xff0c;因其分布式及高吞吐率而被广泛使用&#xff0c;现已与 Cloudera Hadoop、Apache Storm、Apache Spark、Flink 集成。 Kafka 使用场景 页面访问量 PV、页面曝光 Expose、页面点击 Click 等行为事件&#xff1b;实时计…

低分辨率图像中目标检测(附论文下载)

关注并星标 从此不迷路 计算机视觉研究院 公众号ID&#xff5c;ComputerVisionGzq 学习群&#xff5c;扫码在主页获取加入方式 论文地址&#xff1a;https://arxiv.org/pdf/2201.02314.pdf 计算机视觉研究院专栏 作者&#xff1a;Edison_G 超分辨率&#xff08;SR&#xff09;等…

【Openvino03】深入了解OpenVINO™ 工具包与Jupyter Notebooks工程

接上一篇&#xff0c;本篇将以OpenVINO™ 工具包、Jupyter Notebook工具以及OpenVINO™ Notebooks工程为基础&#xff0c;依照构建环境、工具学习、案例学习、实战部署的顺序引导初学者完成从0到1学习人工智能的全过程&#xff0c;希望众多对人工智能感兴趣的开发者&#xff0c…

【多维BFS】ABC308 D

VP的时候居然花了半小时&#xff01; 可恶&#xff01; D - Snuke Maze (atcoder.jp) 题意&#xff1a; 思路&#xff1a; 首先&#xff0c;我们发现到达一个格子之后&#xff0c;下一个格子的字符是确定的 但是&#xff0c;下一个格子到底是哪个是不确定的 下一个格子不…

FreeRTOS源码解析——第一章 整体架构

FreeRTOS源码解析 第一章 FreeRTOS 整体架构 第二章 FreeRTOS 编程规范 第三章 FreeRTOS 内存管理 第四章 FreeRTOS 任务管理 第五章 FreeRTOS 消息队列 第六章 FreeRTOS 软件定时器 第七章 FreeRTOS 信号量 第八章 FreeRTOS 互斥量 第九章 FreeRTOS 任务通知 第十章 FreeRTOS…

算法习题之宏观分层问题

宏观分层 习题1 给定一个正方形矩阵matrix&#xff0c;原地调整成顺时针90度转动的样子习题2 给定一个长方形矩阵matrix&#xff0c;实现转圈打印习题3 给定一个正方形或者长方形矩阵matrix&#xff0c;实现zigzag打印习题4 输入N,在控制台上输出初始边长为N的图案 习题1 给定一…

U盘数据丢失是什么原因?轻松让U盘数据恢复的教程

在数字化时代&#xff0c;我们不可避免地使用各种便携式存储设备&#xff0c;如U盘&#xff0c;来传输和存储重要数据。然而&#xff0c;有时我们可能不小心删除了U盘中的文件&#xff0c;或者格式化了U盘等等而导致数据丢失。这种情况下&#xff0c;你可能会困惑地想知道&…

机器学习——基于Tensorflow和Keras实现卷积神经网络CNN——猫狗分类

文章目录 环境的配置神经网络CNN的介绍卷积前馈神经网络卷积神经网络应用邻域 数据集准备数据预处理构建基准模型 总结什么是过拟合&#xff08;overfit&#xff09;&#xff1f;什么是数据增强&#xff1f;单独制作数据增强&#xff0c;精确率提高了多少&#xff1f; 然后再添…

硬件大熊原创合集(2023/06更新)

06月份更新篇章&#xff1a; 一款射频芯片的layout设计指导案例-篇章1 一款射频芯片的layout设计指导案例-篇章2 警惕超声波工艺对晶振造成损伤 走嵌入式方向&#xff0c;一定要软硬件都懂吗&#xff1f; 6月份广州光亚展&#xff0c;和电子电力大咖文老师见了个面&#xff0c;…

2023车载摄像头9大热点趋势

摘要&#xff1a; 相较于消费类电子摄像头&#xff0c;车载摄像头的工作环境极度恶劣&#xff0c;比如说震动、高温、雨雾、低温、光线变化剧烈等。而车载摄像头以驾驶安全为目的&#xff0c;上述各个工作状态下&#xff0c;均需要能获取稳定、可靠、清晰的周边环境数据。 近年…

HOT36-二叉树的中序遍历

leetcode原题链接&#xff1a;二叉树的中序遍历 题目描述 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2]示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a…

BUUCTF藏藏藏

也是一个图片文件&#xff0c;和一个txt文件 txt文件中是一个提交flag格式&#xff0c;没啥用 拿去010打开后发现可能存在隐藏文件 这个格式说明还有解压文件吧&#xff0c;但是为啥分离不出来呢 刚好有另外一个分离文件的软件foremost 解压后打开在zip文件下有一个福利docx文件…

【零基础入门学习Python---Python网络编程保姆级教程】

&#x1f680; Python &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

GDB寻找segmentation fault位置

一、在当前文件夹下生成指定二进制文件的core文件 查看允许core文件空间大小&#xff1a; ulimit -c修改core文件空间为无限大&#xff1a; ulimit -c unlimited让core文件生成在当前目录下&#xff1a; sudo bash -c echo core.%e.%p > /proc/sys/kernel/core_pattern再…

2023黑马头条.微服务项目.跟学笔记(二)

2023黑马头条.微服务项目.跟学笔记 二 app端文章查看&#xff0c;静态化freemarker,分布式文件系统minIO今日简介学习内容1.文章列表加载1.1 需求分析1.2 表结构分析思考:表的垂直拆分 1.3 导入文章数据库1.3.1 导入数据库1.3.2 导入对应的实体类总结 1.4 实现思路1.4.1 sql练习…

hippo - 提升我们团队工程效率的工具

1. 背景 我们 shopeepay 团队是一个比较大的前端团队&#xff08;80成员&#xff09;&#xff0c;团队内部分布着 react native、javascript npm包、react component npm包、serverless、普通的react工程等多种类型的项目&#xff0c;每种项目类型中的每个项目都有它们自己的配…

Windows 使用Git使用Gitee仓库

1.本地创建文件夹。图中例子&#xff0c;我在桌面创建了文件夹。 2.打开 Git Bash Here. 3.Git Bash 的部分指令。 ls 查看当前文件夹 mkdir gittest01 创建文件夹 cd gittest01 进入文件夹 git init 创建本地仓库 git config --global user.name"chengqian" 创建者…