通常需要长时间连续允许的C# exe程序,要保持无人守护,则需要有守护进程(另外一个exe程序定时检查)
常用办法 是通过 Process对象找到对应的进程是否存在即可判断
获取对应的进程:
1.启动后保存ProcessID
var target = Process.Start(exePath, "auto");
var targetProcessId = target.Id;
// 获取指定ID的进程
var process = Process.GetProcessById(targetID);
if(process==null)
{
// 进程不存在 已退出 ,需要重启
// 重启代码
}
2.通过EXE的允许目录获取
//通过exe的允许路径 查找对应的进程
private Process FindMainProcessByPath(string exePath)
{
foreach (var p in Process.GetProcesses())
{
try
{
if (p.MainModule.FileName == exePath)
{
if (p.Id != Process.GetCurrentProcess().Id)
{
target = p;
break;
}
}
}
catch (Exception ex)
{ }
}
return target;
}
var exePath="C:\\xxxxxxxx.exe";
var process=FindMainProcessByPath(exePath);
if(process==null)
{
// 进程不存在 已退出 ,需要重启
// 重启代码
}
但是如果是进程卡死 ,进程是不会退出的,通过该方法是无法判断程序是否还在正常允许,需要增加如下逻辑
/// <summary>
/// 判断指定进程状态(是否正常运行)
/// </summary>
/// <param name="p"></param>
/// <returns>
/// 进程状态正常:true
/// 进程卡死:false
/// </returns>
public bool checkProcess(Process p)
{
//判断进程是否响应(进程是否整体卡死)
if (p.Responding)
{
//指定进程的总线程数
int thSumCount = p.Threads.Count;
//指定进程的无响应线程数
int suspendCount = 0;
foreach (ProcessThread t in p.Threads)
{
//进程处于等待状态
if (t.ThreadState == System.Diagnostics.ThreadState.Wait)
{
//等待原因为挂起
if (t.WaitReason == ThreadWaitReason.Suspended)
suspendCount++;
}
}
//除了一个异常报错的对话框线程,其他线程都挂起了,说明进程已经卡死
if (thSumCount > 1 && thSumCount == suspendCount + 1)
{
PLogger.Info("target thread(" + thSumCount + "/" + suspendCount + ") is Responding");
return false;
}
//进程及其中线程响应中
return true;
}
else
{
return false;
}
}
这里判断进程是否卡死的通过2个逻辑:
1 process.Responding = false 时 为进程不响应
2 进程下的存在多个线程,仅1个线程在响应
第二点是为了处理 C++的非托管代码报错导致的程序卡死报错