一个C#语言编写Windows服务的例子:强制杀死高内存占用的进程

先说说我遇到的问题,有一台电脑不知道发了什么疯,在开机40-50分钟后会变得非常卡。我打开资源监视器看了下,原来是一个名为scvhost.exe的进程作怪,将这个进程结束掉(事实上Windows会重启这个进程),电脑就又会恢复正常了。

产生这个问题的具体原因现在还没有找到,不过我却想了一个治标的办法,就是写一个Windows服务监视系统内的进程内存占用情况,在剩余可用内存小于15%时,如发现有进程的内存占用超过总内存的45%(也可以是30%或其他数字),则杀死此进程。

我使用的操作系统为Win7旗舰版,VisualStudio版本为2012。

新建项目,找到VisualC#下的Windows服务,建立一个Windows服务项目:

关于建立Windows服务项目,我参考了这篇博客:http://yqin.iteye.com/blog/509583

我建立的项目结构如下:

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页面:

https://msdn.microsoft.com/en-us/library/system.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中。

附:本程序的工程文件可在此地址下载:http://pan.baidu.com/s/1kVCV0ov

END

转载于:https://my.oschina.net/Tsybius2014/blog/729180

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值