1. 下载

  源码下载:http://pan.baidu.com/s/1vqDA2

  安装包下载:http://pan.baidu.com/s/1sjmEB0p

2. 安装注意事项

  • 在配置档中配置你要守护的应用程序,应用程序之间用逗号隔开
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="ProcessAddress" value="
d:\war3.exe,
d:\note.exe,
d:\girl.jpg
" />
</appSettings>
</configuration>

该项目是Windows服务,直接打开“CocoWatcher.exe”会报错,如图1所示:

这个时候先运行【installutil.exe】文件,然后运行该守护程序需安装Windows服务,点击批处理文档【安装.bat】即可,运行之后进入到【管理工具】-【服务】中就能看到有CocoWatcher服务已经启动了,这个时候配置文件中的进程就被保护起来了。这个时候再去任务管理器中去关闭配置文件中的进程就可以发现,已经不能关闭了。

【安装.bat】具体内容如下:

"%cd%\InstallUtil.exe" "%cd%\CocoWatcher.exe"
net start "CocoWatcher"
pause

如果你不想守护进程了,就需要卸载该守护程序,点击批处理文档【卸载.bat】,【卸载.bat】文件具体内容如下:

net stop "CocoWatcher"
"%cd%\InstallUtil.exe" "%cd%\CocoWatcher.exe" -u
taskkill /f /im CocoWatcher.exe
pause

3. 需求分析

  用户指定要守护的应用程序(数量不限),该应用程序不仅包括exe可执行文件,还包括诸如jpg、txt等所有能双击打开执行的应用程序。用户设定好要守护的应用程序后,关闭应用程序(包括合法和非法关闭),该应用程序要能立即重启打开。当电脑重启时,要守护的应用程序也能自动全部打开。

4. 详细设计

  要实现上述需求,首先要提供一个配置档,让用户能随意配置要守护的应用程序。那么,该配置档要配置应用程序的什么信息呢?答案:应用程序的全路径。

  好,我们已经知道了要守护的应用程序的全路径,接下来怎样完成守护任务呢?首先,我们应该打开任务管理器,查看一下正在运行的有哪些进程,然后逐一读取出这些进程的全路径,与要守护的应用程序的全路径比对,如果一致,说明要守护的应用程序已开启了,此时要分配一条线程监控该进程句柄,当该进程句柄返回信息,说明该进程已关闭,此时释放进程句柄内存,并重启该进程。如果遍历任务管理进程列表中所有进程,没有找到与要守护的应用程序的全路径一致的进程,说明要守护的应用程序尚未打开,此时要启动该应用程序,然后转入监控流程。

  值得注意的是,一定要额外分配线程去监控要守护的应用程序,为什么?因为如果你用主线程(入口函数线程)去执行监控任务,会被长期阻塞,直到进程退出才会被激活,这样就无法运行后续程序。况且,监控程序要实现持续监控,要使用死循环,如果主线程进入死循环,就无法监控其他要守护的进程了。

5. 代码详解

  Windows服务的开发步骤,请参考MSDN,此处略去。下面将关键代码贴出,加以解释。

  读取配置档中“ProcessAddress”节点,获取要守护的应用程序全目录,验证应用程序全目录,如果合法,进入扫描任务管理器进程列表流程。

/// <summary>
/// 开始监控
/// </summary>
private void StartWatch()
{
if (this._processAddress != null)
{
if (this._processAddress.Length > )
{
foreach (string str in _processAddress)
{
if (str.Trim() != "")
{
if (File.Exists(str.Trim()))
{
this.ScanProcessList(str.Trim());
}
}
}
}
}
}

打开任务管理器,查看一下正在运行的有哪些进程,然后逐一读取出这些进程的全路径,与要守护的应用程序的全路径比对,如果一致,说明要守护的应用程序已开启了,进入监控流程。如果遍历任务管理进程列表中所有进程,没有找到与要守护的应用程序的全路径一致的进程,说明要守护的应用程序尚未打开,此时要启动该应用程序,然后转入监控流程。

/// <summary>
/// 扫描进程列表,判断进程对应的全路径是否与指定路径一致
/// 如果一致,说明进程已启动
/// 如果不一致,说明进程尚未启动
/// </summary>
/// <param name="strAddress"></param>
private void ScanProcessList(string address)
{
Process[] arrayProcess = Process.GetProcesses();
foreach (Process p in arrayProcess)
{
//System、Idle进程会拒绝访问其全路径
if (p.ProcessName != "System" && p.ProcessName != "Idle")
{
try
{
if (this.FormatPath(address) == this.FormatPath(p.MainModule.FileName.ToString()))
{
//进程已启动
this.WatchProcess(p, address);
return;
}
}
catch
{
//拒绝访问进程的全路径
this.SaveLog("进程(" + p.Id.ToString() + ")(" + p.ProcessName.ToString() + ")拒绝访问全路径!");
}
}
} //进程尚未启动
Process process = new Process();
process.StartInfo.FileName = address;
process.Start();
this.WatchProcess(process, address);
}

分配一条线程,执行监控任务:

 /// <summary>
/// 监听进程
/// </summary>
/// <param name="p"></param>
/// <param name="address"></param>
private void WatchProcess(Process process, string address)
{
ProcessRestart objProcessRestart = new ProcessRestart(process, address);
Thread thread = new Thread(new ThreadStart(objProcessRestart.RestartProcess));
thread.Start();
} public class ProcessRestart
{
//字段
private Process _process;
private string _address; /// <summary>
/// 构造函数
/// </summary>
public ProcessRestart()
{} /// <summary>
/// 构造函数
/// </summary>
/// <param name="process"></param>
/// <param name="address"></param>
public ProcessRestart(Process process, string address)
{
this._process = process;
this._address = address;
} /// <summary>
/// 重启进程
/// </summary>
public void RestartProcess()
{
try
{
while (true)
{
this._process.WaitForExit();
this._process.Close(); //释放已退出进程的句柄
this._process.StartInfo.FileName = this._address;
this._process.Start(); Thread.Sleep();
}
}
catch (Exception ex)
{
ProcessWatcher objProcessWatcher = new ProcessWatcher();
objProcessWatcher.SaveLog("RestartProcess() 出错,监控程序已取消对进程("
+ this._process.Id.ToString() +")(" + this._process.ProcessName.ToString()
+ ")的监控,错误描述为:" + ex.Message.ToString());
}
}
}

用C#实现通用守护进程的更多相关文章

  1. [C#]通用守护进程服务

    摘要 很多情况下,都会使用windows服务做一些任务,但总会有一些异常,导致服务停止.这个时候,开发人员又不能立马解决问题,所以做一个守护者服务还是很有必要的.当检测到服务停止了,重启一下服务,等开 ...

  2. 创建Android守护进程(底层服务)【转】

    本文转载自:https://blog.csdn.net/myfriend0/article/details/80016739 创建Android守护进程(底层服务) 前言 Android底层服务,即运 ...

  3. 深入理解Linux操作系统守护进程的意义

    Linux服务器在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户.提供这些服务的程序是由运行在后台的守护进程(daemons)来执行的.守护进程 ...

  4. 写一个Windows上的守护进程(2)单例

    写一个Windows上的守护进程(2)单例 上一篇的日志类的实现里有个这: class Singleton<CLoggerImpl> 看名字便知其意--单例.这是一个单例模板类. 一个进程 ...

  5. linux守护进程解读

    Linux系统守护进程详解   不要关闭下面这几个服务: acpid, haldaemon, messagebus, klogd, network, syslogd   1. NetworkManag ...

  6. Linux学习之守护进程详解

    Linux系统守护进程详解                                                              ---转自:http://yuanbin.blog ...

  7. python基础-守护进程、守护线程、守护非守护并行

    守护进程 1.守护子进程 主进程创建守护进程  其一:守护进程会在主进程代码执行结束后就终止  其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic pro ...

  8. 守护进程与Supervisor

    博客链接:http://www.cnblogs.com/zhenghongxin/p/8676565.html 消息队列处理后台任务带来的问题 在系统稍微大些的时候,我们经常会用到消息队列(实现的方式 ...

  9. linux分享一:进程全攻略--守护进程(服务)

    概括: 进程是程序的运行实例.进程对应一个唯一的进程PID, 统一程序的多个实例可以同时运行,他们的pid互不相同. 进程一般分为交互进程.批处理进程和守护进程(daemons)三类 一:什么是守护进 ...

随机推荐

  1. Spring实战——无需一行xml配置实现自动化注入

    已经想不起来上一次买技术相关的书是什么时候了,一直以来都习惯性的下载一份电子档看看.显然,如果不是基于强烈的需求或强大的动力鞭策下,大部分的书籍也都只是蜻蜓点水,浮光掠影. 就像有位同事说的一样,有些 ...

  2. 【Python网络爬虫三】 爬去网页新闻

    学弟又一个自然语言处理的项目,需要在网上爬一些文章,然后进行分词,刚好牛客这周的是从一个html中找到正文,就实践了一下.写了一个爬门户网站新闻的程序 需求: 从门户网站爬取新闻,将新闻标题,作者,时 ...

  3. Android Camera 预览图像被拉伸变形的解决方法【转】

    问题描述: 预览图像被拉伸变形 问题原因: 由于预览图像大小跟SurfaceView 大小不一致引起 解决方法: 获取系统支持的所有预览尺寸[getSupportedPictureSizes],然后再 ...

  4. 导入旧版本Android项目时的“Unable to resolve target ‘android

    在Ecplise + ATD + Android SDK的开发中,导入旧版本的Android项目时,往往会出现类似的如下错误 Error:Unable to resolve target 'andro ...

  5. 浅谈 Android 开发文化

    Hello,亲爱的读者朋友们(希望你们是 Android 开发者,或者正在成为 Androider 的路上-)! 质量从用户反馈很清凉然后我们就只能看 CPU 原来的想法是但是事实上不是这些但是我们可 ...

  6. Colored Sticks

    poj2513:http://poj.org/problem?id=2513 题意:就是求一个欧拉回路. 题解:本题是判断欧拉通路是否存在,但是如果是用map的话就会超时,这里采用了trie树,有发现 ...

  7. 在HTML下,如何为多个选择框提取数据并序列化

    如果同时存在选择框及下拉框,如果用JQUERY获取相关数据呢? <form id="deploy-form"> <checkbox>多选框 <sele ...

  8. 【poj3070】矩阵乘法求斐波那契数列

    [题目描述] 我们知道斐波那契数列0 1 1 2 3 5 8 13…… 数列中的第i位为第i-1位和第i-2位的和(规定第0位为0,第一位为1). 求斐波那契数列中的第n位mod 10000的值. [ ...

  9. USB C和USB 3.1傻傻分不清?这篇文章可以帮你

    USB Type-C接口以及USB 3.1标准的到来,理应为消费者提供更多便利.然而就目前来看,似乎这些新标准非但没有为消费者提供了更好的使用体验,反而带来了诸多隐患.Google的工程师Benson ...

  10. C++使用http请求,亲测可用,VS2008编译运行通过

    int CMyFunctionsDlg::request(char* hostname, char* api, char* parameters) { WSADATA WsaData; WSAStar ...