基于C#實現進程回收管理工具
設計初衷
在使用 COM 模式操作 OFFICE 組件的開發(fā)過程中,當操作完相關文檔后,在某些情況下仍然無法釋放掉 Word 或 EXCEL 等應用進程,因此根據進程活動情況或時間點范圍開發(fā)了一個強制殺掉指定進程名稱的 WinForm 程序,做為一種輔助工具運行在云服務器上,命名為 Craneoffice ProcessGC。
開發(fā)運行環(huán)境
操作系統: Windows Server 2019 DataCenter
.net版本: .netFramework4.0 或以上
開發(fā)工具:VS2019 C#
Craneoffice ProcessGC
該工具軟件屬綠色版,無須安裝,直接運行 bin 目錄下的 ProcessGC.exe 即可,同目錄下的 ProcessList.txt 為配置文件,用于配置要釋放的進程,后續(xù)也可用工具程序進行操作。
運行主界面
運行后的主界面如下圖:

主界面顯示了要回收的進程列表,源引于 ProcessList.txt 文件配置,如圖示例我們可以看到欲回收的進程為EXCEL和WORD,下面則顯示已被回收的進程(如果有的話)。
下方顯示 CPU 的利用率和可用內存情況。
系統會隨時監(jiān)測指定的進程名,如果有則按指定的策略進行管理。
管理任務與策略
點擊管理任務選項卡,顯示如下圖:

策略設置如下表:
| 序號 | 項 | 說明 |
|---|---|---|
| 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,執(zhí)行命令行操作 |
| 7 | 相關動作命令 | 當第6項回收動作為Command時,此項為必輸入項,表示要執(zhí)行的 WINDOWS 命令行操作 |
| 8 | 重新啟用命令 | 設置此項,則當關閉或執(zhí)行動作命令后,嘗試執(zhí)行此命令 |
| 9 | 計劃強制關閉時間(小時) | 可以設定小時:分:秒(這個值前綴需要設置一個有效日期),代表每到此時此分此秒,則強制關閉進程 |
通過以上設置,我們可以靈活的對進程的關閉方式進行控制,以達到實際應用的目的。
其它設置
選擇設置選項卡,如下圖:

我們可設置窗口的透明度,另外可以設置兩個選項:
1、只回收本程序啟動時間以后的進程
2、只回收非激活窗口的進程, 指非操作系統顯式的應用進程。
3、管理密碼:默認值為111111,用于關閉應用程序等操作。
移動存儲設備管理
這個選項如下圖:

這是為移動設備存儲數據庫準備的一個選項,點擊停止服務可以有效的、安全的移除存儲設備,也可以繼續(xù)啟動服務。這個選項較少使用,也需要謹慎使用(因為它會嘗試停止IIS、MS SQL SERVER 數據庫服務等)。
核心代碼-計時器監(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可用內存:" + pcmem.NextValue().ToString() + "M";
}
catch (Exception s)
{
}
statusBar1.Text=cur_now.ToString(); //顯示當前時間
Process[] processes; //定義進程組
processes = System.Diagnostics.Process.GetProcesses(); //獲得當前進程組
Process process; //定義初始進程中間變量
string _pname,_killstate=""; //定義進程名變量,及進程回收狀態(tài)字符串
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占用率沒有超過指定的上限,則重置最后的檢測時間為當前時間,繼續(xù)監(jiān)測。
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";
//如果當前進程的內存占用沒有超過指定的上限,則重置最后的檢測時間為當前時間,繼續(xù)監(jiā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;
}
//如果可以回收則在文本框中添加回收狀態(tài),并將進程關閉
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+",執(zhí)行了命令:"+
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
}小結
開發(fā)這款小工具,也是初識 System.Diagnostics(與系統進程、事件日志和性能計數器進行交互的類)的一個過程。
到此這篇關于基于C#實現進程回收管理工具的文章就介紹到這了,更多相關C#進程回收管理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C# string轉換為幾種不同編碼的Byte[]的問題解讀
這篇文章主要介紹了C# string轉換為幾種不同編碼的Byte[]的問題解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02

