基于C#實(shí)現(xiàn)進(jìn)程回收管理工具
設(shè)計(jì)初衷
在使用 COM 模式操作 OFFICE 組件的開(kāi)發(fā)過(guò)程中,當(dāng)操作完相關(guān)文檔后,在某些情況下仍然無(wú)法釋放掉 Word 或 EXCEL 等應(yīng)用進(jìn)程,因此根據(jù)進(jìn)程活動(dòng)情況或時(shí)間點(diǎn)范圍開(kāi)發(fā)了一個(gè)強(qiáng)制殺掉指定進(jìn)程名稱的 WinForm 程序,做為一種輔助工具運(yùn)行在云服務(wù)器上,命名為 Craneoffice ProcessGC。
開(kāi)發(fā)運(yùn)行環(huán)境
操作系統(tǒng): Windows Server 2019 DataCenter
.net版本: .netFramework4.0 或以上
開(kāi)發(fā)工具:VS2019 C#
Craneoffice ProcessGC
該工具軟件屬綠色版,無(wú)須安裝,直接運(yùn)行 bin 目錄下的 ProcessGC.exe 即可,同目錄下的 ProcessList.txt 為配置文件,用于配置要釋放的進(jìn)程,后續(xù)也可用工具程序進(jìn)行操作。
運(yùn)行主界面
運(yùn)行后的主界面如下圖:
主界面顯示了要回收的進(jìn)程列表,源引于 ProcessList.txt 文件配置,如圖示例我們可以看到欲回收的進(jìn)程為EXCEL和WORD,下面則顯示已被回收的進(jìn)程(如果有的話)。
下方顯示 CPU 的利用率和可用內(nèi)存情況。
系統(tǒng)會(huì)隨時(shí)監(jiān)測(cè)指定的進(jìn)程名,如果有則按指定的策略進(jìn)行管理。
管理任務(wù)與策略
點(diǎn)擊管理任務(wù)選項(xiàng)卡,顯示如下圖:
策略設(shè)置如下表:
序號(hào) | 項(xiàng) | 說(shuō)明 |
---|---|---|
1 | 要添加回收的進(jìn)程名 | 請(qǐng)正確添加,無(wú)須輸入擴(kuò)展名,如果不確定名稱則可以通過(guò)任務(wù)管理器進(jìn)行查看 |
2 | 管理策略 | 共分三種方式: 1、Force(默認(rèn)值,表示符合條件則強(qiáng)制關(guān)閉) 2、CPU 3、Memory |
3 | 回收時(shí)間差(秒) | 以秒為單位,記錄進(jìn)程停止活動(dòng)的時(shí)間,超過(guò)停止活動(dòng)時(shí)間的進(jìn)程將被回收 |
4 | 上限指標(biāo) | 1、上限指標(biāo)不能小于零。 2、當(dāng)選用的策略為CPU時(shí),上限指標(biāo)不能大于100(即最高100%占用率) 3、當(dāng)選用的策略為Memory時(shí),指定為Mb值,表示內(nèi)存占用的最高上限 |
5 | 檢測(cè)時(shí)間標(biāo)準(zhǔn) | 共有兩種方式: 1、ByProcess,以進(jìn)程時(shí)間計(jì)算(默認(rèn)) 2、ByNowTime,以啟動(dòng)當(dāng)前時(shí)間計(jì)算 |
6 | 回收動(dòng)作 | 共有兩種方式: 1、Kill,直接關(guān)閉釋放進(jìn)程(默認(rèn)) 2、Command,執(zhí)行命令行操作 |
7 | 相關(guān)動(dòng)作命令 | 當(dāng)?shù)?項(xiàng)回收動(dòng)作為Command時(shí),此項(xiàng)為必輸入項(xiàng),表示要執(zhí)行的 WINDOWS 命令行操作 |
8 | 重新啟用命令 | 設(shè)置此項(xiàng),則當(dāng)關(guān)閉或執(zhí)行動(dòng)作命令后,嘗試執(zhí)行此命令 |
9 | 計(jì)劃強(qiáng)制關(guān)閉時(shí)間(小時(shí)) | 可以設(shè)定小時(shí):分:秒(這個(gè)值前綴需要設(shè)置一個(gè)有效日期),代表每到此時(shí)此分此秒,則強(qiáng)制關(guān)閉進(jìn)程 |
通過(guò)以上設(shè)置,我們可以靈活的對(duì)進(jìn)程的關(guān)閉方式進(jìn)行控制,以達(dá)到實(shí)際應(yīng)用的目的。
其它設(shè)置
選擇設(shè)置選項(xiàng)卡,如下圖:
我們可設(shè)置窗口的透明度,另外可以設(shè)置兩個(gè)選項(xiàng):
1、只回收本程序啟動(dòng)時(shí)間以后的進(jìn)程
2、只回收非激活窗口的進(jìn)程, 指非操作系統(tǒng)顯式的應(yīng)用進(jìn)程。
3、管理密碼:默認(rèn)值為111111,用于關(guān)閉應(yīng)用程序等操作。
移動(dòng)存儲(chǔ)設(shè)備管理
這個(gè)選項(xiàng)如下圖:
這是為移動(dòng)設(shè)備存儲(chǔ)數(shù)據(jù)庫(kù)準(zhǔn)備的一個(gè)選項(xiàng),點(diǎn)擊停止服務(wù)可以有效的、安全的移除存儲(chǔ)設(shè)備,也可以繼續(xù)啟動(dòng)服務(wù)。這個(gè)選項(xiàng)較少使用,也需要謹(jǐn)慎使用(因?yàn)樗鼤?huì)嘗試停止IIS、MS SQL SERVER 數(shù)據(jù)庫(kù)服務(wù)等)。
核心代碼-計(jì)時(shí)器監(jiān)控
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可用內(nèi)存:" + pcmem.NextValue().ToString() + "M"; } catch (Exception s) { } statusBar1.Text=cur_now.ToString(); //顯示當(dāng)前時(shí)間 Process[] processes; //定義進(jìn)程組 processes = System.Diagnostics.Process.GetProcesses(); //獲得當(dāng)前進(jìn)程組 Process process; //定義初始進(jìn)程中間變量 string _pname,_killstate=""; //定義進(jìn)程名變量,及進(jìn)程回收狀態(tài)字符串 bool _kill=false; //是否要回收標(biāo)志變量 bool _phandle=checkBox2.Checked; int _gcSpan; //時(shí)間差變量 DateTime _pdatetime,_checktime,_stdtime; //進(jìn)程啟動(dòng)的時(shí)間變量和檢測(cè)時(shí)間變量 string[] _rv; //接受檢測(cè)結(jié)果的數(shù)組 System.TimeSpan _dd; //時(shí)間差的秒數(shù)變量 // 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]; //獲得當(dāng)前進(jìn)程 _pname=process.ProcessName.ToLower(); //獲得進(jìn)程名并轉(zhuǎn)為小寫 try { _pdatetime = process.StartTime; //獲得進(jìn)程的啟動(dòng)時(shí)間 }catch(Exception e1) { continue; } // _rv=GetSubValueIndex(listBox1,_pname,"|"); //得到要回收的用戶指定進(jìn)程 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) //如果是要回收的進(jìn)程則進(jìn)行處理 { //如果在檢測(cè)數(shù)組沒(méi)有找到,則添加到檢測(cè)數(shù)中 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; //檢測(cè)時(shí)間為當(dāng)前時(shí)間 //開(kāi)始分析CPU策略 if (ref_cl == "cpu") { //如果當(dāng)前進(jìn)程的CPU占用率沒(méi)有超過(guò)指定的上限,則重置最后的檢測(cè)時(shí)間為當(dāng)前時(shí)間,繼續(xù)監(jiān)測(cè)。 if (cur_rank < ref_rank) { _processLastTime[_curpoint] = _checktime; } } }catch(Exception e2) { continue; } //開(kāi)始分析memory策略 if(ref_cl=="memory") { float _curmem=process.WorkingSet/(1024*1024); // richTextBox1.Text+=_pname+" "+_curmem.ToString()+"\r\n"; //如果當(dāng)前進(jìn)程的內(nèi)存占用沒(méi)有超過(guò)指定的上限,則重置最后的檢測(cè)時(shí)間為當(dāng)前時(shí)間,繼續(xù)監(jiān)測(cè)。 if(_curmem<ref_rank) { _processLastTime[_curpoint]=_checktime; } } _gcSpan=ref_span; //得到用戶指定的回收時(shí)間差 _kill=false; _pdatetime=_processLastTime[_curpoint]; //得到進(jìn)程的數(shù)組最后指定時(shí)間 _dd=_checktime-_pdatetime; //時(shí)間差以檢測(cè)時(shí)間 減去 進(jìn)行啟動(dòng)時(shí)間 //如果時(shí)間差大于回收指定時(shí)間則可以回收進(jìn)程,KILL變量為真 if(checkBox1.Checked) { //只回收本程序啟動(dòng)以后的進(jìn)程時(shí)間 if((_dd.TotalSeconds>_gcSpan)&&(_starttime<_pdatetime)) { _kill=true; } } else { if(_dd.TotalSeconds>_gcSpan) { _kill=true; } } //如果初期標(biāo)識(shí)為可以關(guān)閉該進(jìn)程,并且策略為強(qiáng)制性關(guān)閉,則進(jìn)行內(nèi)存判斷 if((_kill)&&(ref_cl=="force")) { //如果內(nèi)存有變化,則表示進(jìn)程仍在活動(dòng),則不進(jìn)行關(guān)閉,并更新檢測(cè)內(nèi)容 int _curmem=process.WorkingSet; label6.Text=_curmem.ToString()+" "+_processLastMem[_curpoint]; if(_curmem!=_processLastMem[_curpoint]) { _processLastTime[_curpoint]=_checktime; _processLastMem[_curpoint]=_curmem; _kill=false; } } //如果指定了強(qiáng)制關(guān)閉時(shí)間,則進(jìn)行判斷 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="強(qiáng)制關(guān)閉計(jì)劃啟動(dòng),計(jì)劃時(shí)間為:"+ref_closetime; } } //如果只回收死進(jìn)程,而當(dāng)前進(jìn)程為激活的窗口的話,則不關(guān)閉 if((_phandle)&&((int)process.MainWindowHandle!=0)) { _kill=false; } //如果可以回收則在文本框中添加回收狀態(tài),并將進(jìn)程關(guān)閉 if(_kill) { if(!process.HasExited) { if(ref_act=="kill") { // MessageBox.Show("has exited"); _killstate=close_tip+".進(jìn)程"+_pname+"已被回收,關(guān)閉策略為"+ref_cl+",動(dòng)作為:"+ref_act+"。進(jìn)程的啟動(dòng)時(shí)間為"+ _pdatetime.ToString()+",檢測(cè)時(shí)間為:"+_checktime.ToString()+ ",現(xiàn)已經(jīng)超時(shí)"+(_dd.TotalSeconds-_gcSpan).ToString()+ "秒,回收時(shí)間單位是"+_gcSpan.ToString()+"秒。"+ "進(jìn)程ID:"+process.Id.ToString()+ "進(jìn)程主窗口句柄:"+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+".進(jìn)程"+_pname+"已被回收,關(guān)閉策略為"+ref_cl+",動(dòng)作為:"+ref_act+",執(zhí)行了命令:"+ ref_cmd1+"。返回值為:"+_return+"。進(jìn)程的啟動(dòng)時(shí)間為"+ _pdatetime.ToString()+",檢測(cè)時(shí)間為:"+_checktime.ToString()+ ",現(xiàn)已經(jīng)超時(shí)"+(_dd.TotalSeconds-_gcSpan).ToString()+ "秒,回收時(shí)間單位是"+_gcSpan.ToString()+"秒。"+ "進(jìn)程ID:"+process.Id.ToString()+ "進(jìn)程主窗口句柄:"+process.MainWindowHandle.ToString(); richTextBox1.AppendText(_killstate+"\r\n"); // process.Kill(); } //清空當(dāng)前進(jìn)程檢測(cè)數(shù)組元素 _processid[_curpoint]=0; _processLastTime[_curpoint]=_checktime; _processLastMem[_curpoint]=0; _processLastCPU[_curpoint]=null; }//判斷進(jìn)程是否已經(jīng)退出 } }//if proecess else //如果沒(méi)有找到進(jìn)程名稱,則二次判斷任務(wù)是否提供了啟動(dòng)命令,如果提供,則運(yùn)行它 { }//end find process name }//li }//for processes = System.Diagnostics.Process.GetProcesses(); //獲得當(dāng)前進(jìn)程組 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]; //獲得當(dāng)前進(jìn)程 string cur_pname=process.ProcessName.ToLower(); //獲得進(jìn)程名并轉(zhuǎn)為小寫 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="進(jìn)程"+ref_process+"嘗試啟動(dòng),關(guān)閉策略為"+ref_cl+",動(dòng)作為:"+ref_act+",啟動(dòng)命令為:"+ ref_cmd2+"。返回值為:"+_return+"。"; richTextBox1.AppendText(_killstate+"\r\n"); } } }//end for listbox }
小結(jié)
開(kāi)發(fā)這款小工具,也是初識(shí) System.Diagnostics(與系統(tǒng)進(jìn)程、事件日志和性能計(jì)數(shù)器進(jìn)行交互的類)的一個(gè)過(guò)程。
到此這篇關(guān)于基于C#實(shí)現(xiàn)進(jìn)程回收管理工具的文章就介紹到這了,更多相關(guān)C#進(jìn)程回收管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
向一個(gè)數(shù)組中插入一個(gè)1~100的隨機(jī)數(shù)
這篇文章主要介紹了如何向一個(gè)數(shù)組中插入一個(gè)1~100的隨機(jī)數(shù),思路很簡(jiǎn)單,需要的朋友可以參考下2014-07-07C# string轉(zhuǎn)換為幾種不同編碼的Byte[]的問(wèn)題解讀
這篇文章主要介紹了C# string轉(zhuǎn)換為幾種不同編碼的Byte[]的問(wèn)題解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02C#實(shí)現(xiàn)二叉排序樹(shù)代碼實(shí)例
今天小編就為大家分享一篇關(guān)于C#實(shí)現(xiàn)二叉排序樹(shù)代碼實(shí)例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-10-10C# Winform截圖指定控件范圍內(nèi)的圖像的流程步驟
工作所需,需要截圖軟件跑出來(lái)的界面上的圖表,但是窗口本身是可以縮放的,圖表也是做的可以跟著窗體大小一起縮放,所以就寫了一個(gè)函數(shù),用于截圖圖表容器內(nèi)的圖像,文中有函數(shù)源碼供大家參考,需要的朋友可以參考下2024-10-10C#實(shí)現(xiàn)將PDF轉(zhuǎn)為Excel的方法詳解
通常,PDF格式的文檔能支持的編輯功能不如office文檔多,針對(duì)PDF文檔里面有表格數(shù)據(jù)的,如果想要編輯表格里面的數(shù)據(jù),可以將該P(yáng)DF文檔轉(zhuǎn)為Excel格式。本文將介紹如何利用C#實(shí)現(xiàn)PDF轉(zhuǎn)Excel,需要的可以參考一下2022-04-04