进程"/>
一个C#语言编写Windows服务的例子:强制杀死高内存占用的进程
先说说我遇到的问题,有一台电脑不知道发了什么疯,在开机40-50分钟后会变得非常卡。我打开资源监视器看了下,原来是一个名为scvhost.exe的进程作怪,将这个进程结束掉(事实上Windows会重启这个进程),电脑就又会恢复正常了。
产生这个问题的具体原因现在还没有找到,不过我却想了一个治标的办法,就是写一个Windows服务监视系统内的进程内存占用情况,在剩余可用内存小于15%时,如发现有进程的内存占用超过总内存的45%(也可以是30%或其他数字),则杀死此进程。
我使用的操作系统为Win7旗舰版,VisualStudio版本为2012。
新建项目,找到VisualC#下的Windows服务,建立一个Windows服务项目:
关于建立Windows服务项目,我参考了这篇博客:
我建立的项目结构如下:
ServiceMain.cs,为项目自动创建的cs文件(原名为Service1,我改名为ServiceMain),ServiceMain类继承自ServiceBase
1、CanPauseAndContinue设置为True
2、CanShutdown设置为True
3、ServiceName设置为ProcessMonitor
4、在设计器界面单击鼠标右键,点击“添加安装程序”,生成ProjectInstall.cs
ProjectInstall.cs,ProjectInstall类继承自System.Configuration.Install.Installer,其中:
System.ServiceProcess.ServiceInstaller类实例serviceInstaller
1、Description设置为“进程杀手”
2、DisplayName设置为ProcessMonitor
3、StartType设置为Automatic(包括自动、手动、禁用,这里选择自动)
System.ServiceProcess.ServiceProcessInstaller类实例serviceProcessInstaller
1、Account设置为LocalSystem(指定运行此服务的用户类型)
下面开始写代码,在ServiceMain.cs中添加如下代码:
using Microsoft.VisualBasic.Devices;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;namespace ProcessMonitor
{public partial class ServiceMain : ServiceBase{/// <summary>/// 进程监测计时器/// </summary>System.Timers.Timer timerScanner = new System.Timers.Timer();LinkedList<int> lstProc = new LinkedList<int>();/// <summary>/// 剩余内存小于此百分比时才会杀死高内存占用进程/// </summary>private double PERCENT_AT = 0.15;/// <summary>/// 杀死内存占用百分比高于此数值的进程/// </summary>private double PERCENT_PT = 0.45;public ServiceMain(){InitializeComponent();}protected override void OnStart(string[] args){base.OnStart(args);EventLog.WriteEntry("PROCESS MONITOR: START");timerScanner.Enabled = true;timerScanner.Elapsed += timerScanner_Tick;timerScanner.Interval = 10000;timerScanner.Start();}protected override void OnPause(){EventLog.WriteEntry("PROCESS MONITOR: PAUSE");base.OnPause();}protected override void OnContinue(){base.OnContinue();EventLog.WriteEntry("PROCESS MONITOR: CONTINUE");}protected override void OnStop(){EventLog.WriteEntry("PROCESS MONITOR: STOP");base.OnStop();}private void timerScanner_Tick(object sender, EventArgs e){try{EventLog.WriteEntry("PROCESS MONITOR: CHECK PROCESSES...");ComputerInfo cInfo = new ComputerInfo();long totalPhyMem = Convert.ToInt64(cInfo.TotalPhysicalMemory);long availablePhyMem = Convert.ToInt64(cInfo.AvailablePhysicalMemory);double percentATMem = availablePhyMem * 1.0 / totalPhyMem;if (percentATMem < PERCENT_AT){foreach (Process proc in Process.GetProcesses()){long procMem = proc.WorkingSet64;double percentPTMem = procMem * 1.0 / totalPhyMem;if (percentPTMem > PERCENT_PT && !lstProc.Contains(proc.Id)){EventLog.WriteEntry("PROCESS MONITOR: KILL PROCESS " + proc.ProcessName);proc.Kill();}}}}catch (Exception ex){EventLog.WriteEntry(ex.Message, EventLogEntryType.Error);}}}
}
关于这段代码,有以下几点说明:
1、需要手动添加引用Microsoft.VisualBasic,支持对命名空间Microsoft.VisualBasic.Devices的引用。
2、Timer千万不要从可视化编辑器的组件库中拖入,因为Windows服务不支持System.Windows.Forms.Timer,我们使用的Timer是System.Timers.Timer。
3、不要在代码中使用诸如MessageBox之类的UI,写日志可以使用EventLog,记录下的日志可以在Windows事件查看器中查到。
有关EventLog的使用说明,可参考相关MSDN页面:
.diagnostics.eventlog(VS.71).aspx
代码编写完毕后,生成解决方案,此时可在Debug目录中找到编译好的ProcessMonitor.exe。
安装服务可以通过VS提供的InstallUtil工具实现,用管理员身份打开VS开发人员命令提示,输入命令:
InstallUtil ProcessMonitor.exe所在绝对路径
安装完毕后,就可以在Windows的服务列表中找到此服务了
启动该服务后,ProcessMonitor就可以正式开始工作了!
我们可在事件查看器中找到EventLog打印的相关日志:
如果需要卸载此服务,在安装命令的基础上,添加一个命令行参数/u即可:
InstallUtil /u ProcessMonitor.exe所在绝对路径
这些内容都会被同时写入ProcessMonitor.exe同目录下的日志文件ProcessMonitor.InstallLog中。
附:本程序的工程文件可在此地址下载:
END
转载于:
更多推荐
一个C#语言编写Windows服务的例子:强制杀死高内存占用的进程
发布评论