C# 关于进程回收管理的一款工具设计与分享

news2024/9/23 1:38:14

目录

设计初衷

开发运行环境

Craneoffice ProcessGC

运行主界面

管理任务与策略

其它设置

移动存储设备管理

核心代码-计时器监控

小结


设计初衷

在使用 COM 模式操作 OFFICE 组件的开发过程中,当操作完相关文档后,在某些情况下仍然无法释放掉 Word 或 EXCEL 等应用进程,因此根据进程活动情况或时间点范围开发了一个强制杀掉指定进程名称的 WinForm 程序,做为一种辅助工具运行在云服务器上,命名为 Craneoffice ProcessGC。

开发运行环境

操作系统: Windows Server 2019 DataCenter

.net版本: .netFramework4.0 或以上

开发工具:VS2019  C#

Craneoffice ProcessGC

该工具软件属绿色版,无须安装,直接运行 bin 目录下的 ProcessGC.exe 即可,同目录下的 ProcessList.txt 为配置文件,用于配置要释放的进程,后续也可用工具程序进行操作。

运行主界面

运行后的主界面如下图:

主界面显示了要回收的进程列表,源引于 ProcessList.txt 文件配置,如图示例我们可以看到欲回收的进程为EXCEL和WORD,下面则显示已被回收的进程(如果有的话)。

下方显示 CPU 的利用率和可用内存情况。

系统会随时监测指定的进程名,如果有则按指定的策略进行管理。

管理任务与策略

点击管理任务选项卡,显示如下图:

策略设置如下表:

序号说明
1要添加回收的进程名请正确添加,无须输入扩展名,如果不确定名称则可以通过任务管理器进行查看
2管理策略

共分三种方式:

1、Force(默认值,表示符合条件则强制关闭)

2、CPU

3、Memory

3回收时间差(秒)以秒为单位,记录进程停止活动的时间,超过停止活动时间的进程将被回收
4上限指标

1、上限指标不能小于零。

2、当选用的策略为CPU时,上限指标不能大于100(即最高100%占用率)

3、当选用的策略为Memory时,指定为Mb值,表示内存占用的最高上限

5检测时间标准

共有两种方式:

1、ByProcess,以进程时间计算(默认)

2、ByNowTime,以启动当前时间计算

6回收动作

共有两种方式:

1、Kill,直接关闭释放进程(默认)

2、Command,执行命令行操作

7相关动作命令当第6项回收动作为Command时,此项为必输入项,表示要执行的 WINDOWS 命令行操作
8重新启用命令设置此项,则当关闭或执行动作命令后,尝试执行此命令
9计划强制关闭时间(小时)可以设定小时:分:秒(这个值前缀需要设置一个有效日期),代表每到此时此分此秒,则强制关闭进程

通过以上设置,我们可以灵活的对进程的关闭方式进行控制,以达到实际应用的目的。

其它设置

选择设置选项卡,如下图:

我们可设置窗口的透明度,另外可以设置两个选项:

1、只回收本程序启动时间以后的进程

2、只回收非激活窗口的进程, 指非操作系统显式的应用进程。

3、管理密码:默认值为111111,用于关闭应用程序等操作。

移动存储设备管理

这个选项如下图:

这是为移动设备存储数据库准备的一个选项,点击停止服务可以有效的、安全的移除存储设备,也可以继续启动服务。这个选项较少使用,也需要谨慎使用(因为它会尝试停止IIS、MS SQL SERVER 数据库服务等)。

核心代码-计时器监控

		private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
		{
			DateTime cur_now=System.DateTime.Now;
			int cur_hour=cur_now.Hour;
			int cur_min=cur_now.Minute;
			int cur_sec=cur_now.Second;
		
			pc.CategoryName="Processor";
			pc.CounterName="% Processor Time";
			pc.InstanceName="_Total";
			
//			pc.MachineName="michaeljane";
			float pcv=pc.NextValue();
			label7.Text="CPU利用率:"+(pcv).ToString()+" %";
			cpubar.Value=(int)(pcv);

			pcmem.CategoryName="Memory";
			pcmem.CounterName="Available MBytes";
			pcmem.InstanceName=null;

//			richTextBox1.Text=pcpu.NextValue().ToString()+"\r\n";
			

			/*			System.Diagnostics.PerformanceCounter[] mypc; 
			System.Diagnostics.PerformanceCounterCategory mycat = 
				new System.Diagnostics.PerformanceCounterCategory("process");
			// Remove the current contents of the list.
			// Retrieve the counters.
			mypc = mycat.GetCounters();
			// Add the retrieved counters to the list.
			richTextBox1.Text="";
			for (int i = 0; i < mypc.Length; i++) 
			{ 
				richTextBox1.Text+=(mypc[i].CounterName)+"\r\n";
			}
*/

//			float cpuLoad = pc.NextValue();
            try
            {
                label7.Text += "\r\n可用内存:" + pcmem.NextValue().ToString() + "M";
            }
            catch (Exception s)
            {
            }
			statusBar1.Text=cur_now.ToString();  //显示当前时间
			Process[] processes; //定义进程组
			processes = System.Diagnostics.Process.GetProcesses(); //获得当前进程组
			Process process;  //定义初始进程中间变量
			string _pname,_killstate="";   //定义进程名变量,及进程回收状态字符串
			bool _kill=false;  //是否要回收标志变量
			bool _phandle=checkBox2.Checked;
			int _gcSpan;  //时间差变量
			DateTime _pdatetime,_checktime,_stdtime; //进程启动的时间变量和检测时间变量
			string[] _rv;    //接受检测结果的数组
			System.TimeSpan _dd; //时间差的秒数变量
//			string[] _processid=new string[1000];
//			DateTime[] _processLastTime=new DateTime[1000];
//			int[] _processLastMem=new int[1000];
				for(int i = 0;i<processes.Length-1;i++)
				{
					process= processes[i];  //获得当前进程
					_pname=process.ProcessName.ToLower();  //获得进程名并转为小写
                try
                {
                    _pdatetime = process.StartTime;  //获得进程的启动时间
                }catch(Exception e1)
                {
                    continue;
                }
					//				_rv=GetSubValueIndex(listBox1,_pname,"|");  //得到要回收的用户指定进程
					for(int li=0;li<listBox1.Items.Count;li++)
					{
						_rv=listBox1.Items[li].ToString().Split('|');
						string ref_process=_rv[0].ToLower().Trim();
						int ref_span=int.Parse(_rv[1].ToString());
						string ref_cl=_rv[2].ToLower().Trim();
						float ref_rank=float.Parse(_rv[3].ToString());
						string ref_stdtime=_rv[4].ToLower().Trim();
						string ref_act=_rv[5].ToLower().Trim();
						string[] ref_cmd1=_rv[6].Split('↙');
						string[] ref_cmd2=_rv[7].Split('↙');
						string ref_closetime=_rv[8].Trim();
						//				richTextBox1.Text+=_rv[0]+_rv[1]+"\r\n";
					
						if(ref_process==_pname)  //如果是要回收的进程则进行处理
						{
							//如果在检测数组没有找到,则添加到检测数中
							int _curpoint=System.Array.IndexOf(_processid,process.Id);
							if(_curpoint<0)
							{
								_stdtime=process.StartTime;
								if(ref_stdtime=="bynowtime")
								{
									_stdtime=System.DateTime.Now;
								}
								System.Diagnostics.PerformanceCounter pcm=new System.Diagnostics.PerformanceCounter("Process","% Processor Time",_pname);
                            try
                            {
                                AddArray(process.Id, _stdtime, process.WorkingSet, pcm);
                            }catch(Exception e3)
                            {

                            }
								continue;
							}
                        //						richTextBox1.Text+=((System.Diagnostics.PerformanceCounter)_processLastCPU[_curpoint]).NextValue().ToString()+"\r\n";
                        try
                        {
                            float cur_rank = ((System.Diagnostics.PerformanceCounter)_processLastCPU[_curpoint]).NextValue();
                            _checktime = System.DateTime.Now;  //检测时间为当前时间
                                                               //开始分析CPU策略
                            if (ref_cl == "cpu")
                            {
                                //如果当前进程的CPU占用率没有超过指定的上限,则重置最后的检测时间为当前时间,继续监测。
                                if (cur_rank < ref_rank)
                                {
                                    _processLastTime[_curpoint] = _checktime;
                                }
                            }
                        }catch(Exception e2)
                        {
                            continue;
                        }
							//开始分析memory策略
							if(ref_cl=="memory")
							{
								float _curmem=process.WorkingSet/(1024*1024);
								//							richTextBox1.Text+=_pname+" "+_curmem.ToString()+"\r\n";
								//如果当前进程的内存占用没有超过指定的上限,则重置最后的检测时间为当前时间,继续监测。
								if(_curmem<ref_rank)
								{
									_processLastTime[_curpoint]=_checktime;
								}
							}
							_gcSpan=ref_span;  //得到用户指定的回收时间差
							_kill=false;
							_pdatetime=_processLastTime[_curpoint]; //得到进程的数组最后指定时间
							_dd=_checktime-_pdatetime;     //时间差以检测时间 减去 进行启动时间
							//如果时间差大于回收指定时间则可以回收进程,KILL变量为真
							if(checkBox1.Checked)
							{
								//只回收本程序启动以后的进程时间
								if((_dd.TotalSeconds>_gcSpan)&&(_starttime<_pdatetime))
								{
									_kill=true;
								}
							}
							else
							{
								if(_dd.TotalSeconds>_gcSpan)
								{
									_kill=true;
								}
							}
							//如果初期标识为可以关闭该进程,并且策略为强制性关闭,则进行内存判断
							if((_kill)&&(ref_cl=="force"))
							{
								//如果内存有变化,则表示进程仍在活动,则不进行关闭,并更新检测内容
								int _curmem=process.WorkingSet;
								label6.Text=_curmem.ToString()+"  "+_processLastMem[_curpoint];
								if(_curmem!=_processLastMem[_curpoint])
								{
									_processLastTime[_curpoint]=_checktime;
									_processLastMem[_curpoint]=_curmem;
									_kill=false;
								}
							}
							//如果指定了强制关闭时间,则进行判断
							string close_tip="";
							if(ref_closetime!="")
							{
								DateTime ref_cls=DateTime.Parse(ref_closetime);
								if((ref_cls.Hour==cur_hour)&&(ref_cls.Minute==cur_min)&&(ref_cls.Second==cur_sec))
								{
									_kill=true;
								    close_tip="强制关闭计划启动,计划时间为:"+ref_closetime;
								}
							}
							//如果只回收死进程,而当前进程为激活的窗口的话,则不关闭
							if((_phandle)&&((int)process.MainWindowHandle!=0))
							{
								_kill=false;
							}

							//如果可以回收则在文本框中添加回收状态,并将进程关闭
							if(_kill)
							{
								if(!process.HasExited)
								{
									if(ref_act=="kill")
									{
										//								MessageBox.Show("has exited");
										_killstate=close_tip+".进程"+_pname+"已被回收,关闭策略为"+ref_cl+",动作为:"+ref_act+"。进程的启动时间为"+
											_pdatetime.ToString()+",检测时间为:"+_checktime.ToString()+
											",现已经超时"+(_dd.TotalSeconds-_gcSpan).ToString()+
											"秒,回收时间单位是"+_gcSpan.ToString()+"秒。"+
											"进程ID:"+process.Id.ToString()+
											"进程主窗口句柄:"+process.MainWindowHandle.ToString();
										process.Kill();
										richTextBox1.AppendText(_killstate+"\r\n");
									}
									if(ref_act=="command")
									{
										//								MessageBox.Show("has exited");
										string _return="";
										for(int st=0;st<ref_cmd1.GetLength(0);st++)
										{
											_return+=ref_cmd1[st]+" Result:"+WinExec(ref_cmd1[st],0).ToString()+"↙";
										}
										_killstate=close_tip+".进程"+_pname+"已被回收,关闭策略为"+ref_cl+",动作为:"+ref_act+",执行了命令:"+
											ref_cmd1+"。返回值为:"+_return+"。进程的启动时间为"+
											_pdatetime.ToString()+",检测时间为:"+_checktime.ToString()+
											",现已经超时"+(_dd.TotalSeconds-_gcSpan).ToString()+
											"秒,回收时间单位是"+_gcSpan.ToString()+"秒。"+
											"进程ID:"+process.Id.ToString()+
											"进程主窗口句柄:"+process.MainWindowHandle.ToString();
										richTextBox1.AppendText(_killstate+"\r\n");
										//										process.Kill();
									}
									//清空当前进程检测数组元素
									_processid[_curpoint]=0;
									_processLastTime[_curpoint]=_checktime;
									_processLastMem[_curpoint]=0;
									_processLastCPU[_curpoint]=null;
								}//判断进程是否已经退出
							}
						}//if proecess
						else //如果没有找到进程名称,则二次判断任务是否提供了启动命令,如果提供,则运行它
						{
						}//end find process name
					}//li
				}//for
			processes = System.Diagnostics.Process.GetProcesses(); //获得当前进程组
			for(int ali=0;ali<listBox1.Items.Count;ali++)
			{
				_rv=listBox1.Items[ali].ToString().Split('|');
				string ref_process=_rv[0].ToLower().Trim();
				int ref_span=int.Parse(_rv[1].ToString());
				string ref_cl=_rv[2].ToLower().Trim();
				float ref_rank=float.Parse(_rv[3].ToString());
				string ref_stdtime=_rv[4].ToLower().Trim();
				string ref_act=_rv[5].ToLower().Trim();
				string[] ref_cmd1=_rv[6].Split('↙');
				string ref_start_cmd=_rv[7];
				string[] ref_cmd2=_rv[7].Split('↙');
				bool _find=false;
				if(ref_start_cmd!="")
				{
					for(int i = 0;i<processes.Length-1;i++)
				    {
					  process= processes[i];  //获得当前进程
					  string cur_pname=process.ProcessName.ToLower();  //获得进程名并转为小写
						if(cur_pname==ref_process)
						{
							_find=true;
						}
				    }
					if(!_find)
					{
						string _return="";
						for(int st=0;st<ref_cmd2.GetLength(0);st++)
						{
							_return+=ref_cmd2[st]+" Result:"+WinExec(ref_cmd2[st],0).ToString()+"↙";
						}
						_killstate="进程"+ref_process+"尝试启动,关闭策略为"+ref_cl+",动作为:"+ref_act+",启动命令为:"+
							ref_cmd2+"。返回值为:"+_return+"。";
						richTextBox1.AppendText(_killstate+"\r\n");
					}
				}
			}//end for listbox

		}

小结

开发这款小工具,也是初识 System.Diagnostics(与系统进程、事件日志和性能计数器进行交互的类)的一个过程。

这里可以下载完整源码:https://download.csdn.net/download/michaelline/89140846

工具仅作学习使用,大家感兴趣的话可以按照自己的需求进行修改,感谢您的阅读,希望本文能对您有所帮助。

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

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

相关文章

2024.4.19 Python爬虫复习day07 可视化3

综合案例 需求: 已知2020年疫情数据,都是json数据,需要从文件中读出,进行处理和分析,最终实现数据可视化折线图 相关知识点: json json简介: 本质是一个特定格式的字符串 举例: [{},{},{}] 或者 {}python中json包: import jsonpython数据转为json数据: 变量接收json…

Unity类银河恶魔城学习记录12-17 p139 In game UI源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili UI.cs using UnityEngine;public class UI : MonoBehaviour {[SerializeFie…

kworker(kworker/u2:1,kworker/0:13,kworker/0:1H) 工作队列的命名

1、概述 工作队列是除软中断和tasklet以外最常用的下半部机制之一。工作队列的基本原理是把work(需要推迟执行的函数)交由一个内核线程来异步执行。关于工作队列的具体使用请读者参考其他资料&#xff0c;本文不再概述。 在创建工作队列时,可以通过flag参数指定创建的工作队列…

(四)C++自制植物大战僵尸游戏启动流程

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/ErelL 一、启动方式 鼠标左键单机VS2022上方工具栏中绿色三角按钮&#xff08;本地Windows调试器&#xff09;进行项目启动。第一次启动项目需要编译项目中所有代码文件&#xff0c;编译生成需要一定的时间。不同性能的电…

AVB简介(二): gPTP简介

AVB简介&#xff08;二&#xff09;: gPTP简介 一、时间同步要解决的问题二、gPTP的主要思想2.1 体系结构2.2 主时钟选取2.3 绝对时间同步2.4 相对时间同步 三、影响校时精度的因素3.1 传输时延不对称3.2 驻留时间3.3 时间戳采样点3.4 时钟频率3.5 传输路径延时测量方式3.6 时钟…

idea运行Tomcat,控制台日志的中文乱码

一 版本 win10&#xff0c;idea2022,jdk18,tomcat9 二 问题描述 在idea上可以运行Tomcat。服务器启动后&#xff0c;可以正常访问本地的html文件。但是控制台的Tomcat日志出现了乱码&#xff1a;server与Tomcat Catlina Log两处。 三 无效的解决之道 1 idea的Help选项Edit …

Spring ORM

Spring Data JPA 作为Spring Data 中对于关系型数据库支持的一种框架技术,属于 ORM 的一种,通过得当的使用,可以大大简化开发过程中对于数据操作的复杂度。 Java里面写的一段DB操作逻辑,是如何一步步被传递到 DB 中执行了的呢?为什么 Java 里面可以去对接不同产商的 DB 产…

ExtendSim花生酱加工厂模型

该模型展示了ExtendSim可靠性模块与ExtendeSim离散速率技术相结合的协同作用。 在花生酱加工厂的最初阶段&#xff0c;花生经过烘烤和冷却。冷却后的花生经过热烫或水烫去外皮。这些经过漂白的花生进入过程的混合部分&#xff0c;在研磨机中用盐、葡萄糖和氢化油稳定剂将其粉碎…

MySQL排序你真的掌握了吗?5个问题考考你

测试sql数据 CREATE TABLE student (id int NOT NULL AUTO_INCREMENT,name varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,age int DEFAULT NULL,money int DEFAULT NULL,PRIMARY KEY (id) USING BTREE,KEY index_name (age) ); INSERT INTO st…

【Linux】线程的控制

目录 POSIX线程库 常用的POSIX线程库接口声明&#xff1a; 注意事项 创建一个进程 pthread_create函数 参数 返回值 使用示例 线程ID和进程地址空间布局 线程ID 进程地址空间布局 示例图 获取一个进程的线程ID 函数原型 返回值 使用示例 注意事项 线程终止 p…

SpringBoot项目整合ACTable实现实体类快速生产数据库表

1.安装 ACTable依赖 <dependency> <groupId>com.gitee.sunchenbin.mybatis.actable</groupId> <artifactId>mybatis-enhance-actable</artifactId> <version>1.5.0.RELEASE</version> </dependency> 使用mybatis…

如何做一个springboot的starter类型的SDK

关键的东西 首先我们是一个starter类型的SDK&#xff0c;为了给调用者使用&#xff0c;其中有一些Bean我们会放到SDK中&#xff0c;并且这些Bean能够注入到调用者的Spring容器中。 最关键的spring.factories文件 这个文件所在位置如下图所示&#xff0c;该文件通过写入一下代…

自定义vue-cli 实现预设模板项目

模板结构 主要包括四个部分&#xff1a; preset.jsonprompts.jsgenerator/index.jstemplate/ 项目最终结构 preset.json preset.json 中是一个包含创建新项目所需预定义选项和插件的 JSON 对象&#xff0c;让用户无需在命令提示中选择它们&#xff0c;简称预设&#xff1b;…

文献速递:深度学习肝脏肿瘤诊断---基于深度学习的肝细胞结节性病变在整片组织病理图像上的分类

Title 题目 Deep Learning-Based Classification of Hepatocellular Nodular Lesions on Whole-Slide Histopathologic Images 基于深度学习的肝细胞结节性病变在整片组织病理图像上的分类 Background 背景 Hepatocellular nodular lesions (HNLs) constitute a heterogen…

Offer必备算法26_BFS解决最短路_四道力扣题(由易到难)

目录 ①力扣1926. 迷宫中离入口最近的出口 解析代码 ②力扣433. 最小基因变化 解析代码 ③力扣127. 单词接龙 解析代码 ④力扣675. 为高尔夫比赛砍树 解析代码 本篇完。 ①力扣1926. 迷宫中离入口最近的出口 1926. 迷宫中离入口最近的出口 难度 中等 给你一个 m x …

SpringBoot学习(二)WEB开发

文章目录 WEB开发WebMvcAutoConfiguration原理生效条件效果WebMvcConfigurer接口静态资源源码规则EnableWebMvcConfiguration规则容器中WebMvcConfigurer配置底层行为 Web场景自动配置默认效果 静态资源默认规则静态资源映射静态资源缓存欢迎页Favion 自定义静态资源规则配置方…

PINet车道线检测+YOLOv8视频目标检测

前言&#xff1a; 本文主要目的是实现在PINet车道线检测的代码中嵌入YOLOv8的目标检测模块&#xff0c;具体效果如图所示&#xff1a; 在学习和使用YOLOv8进行目标检测时&#xff0c;感觉可以和最近研究的车道线检测项目结合起来&#xff0c;形成一套如上图所示的视频效…

2024/4/14周报

文章目录 摘要Abstract文献阅读题目创新点CROSSFORMER架构跨尺度嵌入层&#xff08;CEL&#xff09;CROSSFORMER BLOCK长短距离注意&#xff08;LSDA&#xff09;动态位置偏置&#xff08;DPB&#xff09; 实验 深度学习CrossFormer背景维度分段嵌入&#xff08;DSW&#xff09…

【图像分类】基于深度学习的轴承和齿轮识别(ResNet网络)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。(专栏订阅用户订阅专栏后免费提供数据集和源码一份,超级VIP用户不在服务范围之内,不想订阅专栏的兄弟们可以私信…

如何远程连接电脑?

远程连接电脑是一种技术&#xff0c;能够使用户在不同地点的电脑之间建立连接&#xff0c;实现互相访问和控制的功能。这项技术为我们提供了便利和效率&#xff0c;使得随时随地的协同办公、异地统一管理和远程数据采集管理成为可能。 【天联】的使用场景 远程连接电脑的应用非…