http://www.cnblogs.com/fujinliang/archive/2012/09/13/2684165.html 原文地址
http://www.2cto.com/kf/201504/391343.html
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx 错误代码
需求:很多时候我们需要后台运行几个Console来不停的计算数据,那么部署到客户服务器后,如果出现突发异常,程序挂掉了,那。。。?
解决方案:封装了一个对后台运行程序不停监测的功能,如果发现程序有异常,但是进程还在,这个时候就Kill掉这个进程,重启后台计算程序,这里的计算程序均为"控制台运行程序"。
异常中可以看到,Kill()进程的时候出现"拒绝访问",在网上搜了下,
解决方案大致就这几种: 在config里增加identity
<system.web>
<identity impersonate="true" userName="Administrator" password="123456" />
</system.web>
检测程序用"管理员身份运行"对监测的程序目录分配权限结果是这几种方式都没能解决此问题。
我查看了Kill()方法的注释:
// // 摘要:
// 立即停止关联的进程。
// // 异常:
// System.ComponentModel.Win32Exception:
// 未能终止关联的进程。 - 或 - 正在终止该进程。 - 或 - 关联的进程是一个 Win16 可执行文件。
// // System.NotSupportedException:
// 您正尝试为远程计算机上运行的进程调用 System.Diagnostics.Process.Kill()。
该方法仅对在本地计算机上运行的进程可用。 // //
System.InvalidOperationException:
// 该进程已经退出。 - 或 - 没有与此 System.Diagnostics.Process 对象关联的进程。
public void Kill();
发现是一个Win32Exception的异常,随后我又查阅了ms的官方文档,果然有发现:
大概意思就是说如果这个监测程序是Console,這样写是没问题的,可以正常结束掉进程。但这里因为需要在界面上展现出一些监测数据,这里我用的是WPF,也就是文档里说的图像界面程序。
MS的原话是这样的:如果调用 Kill,则可能丢失进程编辑的数据或分配给进程的资源。
Kill
导致进程不正常终止,因而只应在必要时使用。CloseMainWindow
使进程能够有序终止并关闭所有窗口,所以对于有界面的应用程序,使用它更好。如果 CloseMainWindow 失败,则可以使用
Kill终止进程。Kill
是终止没有图形化界面的进程的唯一方法。 将Kill方法()改成了CloseMainWindow()即可正常杀掉进程。
调用PDA中的接口调试,程序直接死了,不能结束进程,要重启wince系统。复制到PDA中程序可以正常调用扫码接口,未解之谜。。。此代码一部分用处在于此 ,尴尬。
主要代码
[MTAThread] private static void Main() { try { IntPtr handle = CreateToolhelp32Snapshot((uint)SnapShotFlags.TH32CS_SNAPPROCESS, 0); var pDictionary = new Dictionary<int, string>(); var strAppName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; if ((int)handle != -1) { var pe32 = new Processentry32 { dwSize = (uint)Marshal.SizeOf(typeof(Processentry32)) }; int bMore = Process32First(handle, ref pe32); Processentry32 pe; Log.WriteLog("start:" + handle.ToString()); while (bMore == 1) { IntPtr temp = Marshal.AllocHGlobal((int)pe32.dwSize); Marshal.StructureToPtr(pe32, temp, true); pe = (Processentry32)Marshal.PtrToStructure(temp, typeof(Processentry32)); Marshal.FreeHGlobal(temp); Log.WriteLog(pe32.szExeFile + ":" + pe.th32ProcessID); pDictionary.Add((int)pe.th32ProcessID, pe.szExeFile); bMore = Process32Next(handle, ref pe32); } } var c = pDictionary.Values.ToList().Where(x => x.StartsWith(strAppName)).ToList(); var ic = c.Count; if (ic >= 2) { var p = pDictionary.Where(x => x.Value.StartsWith(strAppName)); if (MsgBoxs.ShowQMsgYes("检测到已运行该程序,是否结束上一个进程") == DialogResult.Yes) { foreach (KeyValuePair<int, string> keyValuePair in p) { try { if (p.LastOrDefault().Key == keyValuePair.Key) break; Process cProcess = Process.GetProcessById(keyValuePair.Key); cProcess.CloseMainWindow(); //cProcess.Kill();//进程异常结束会杀不死进程并且报 Win32Exception Log.WriteLog("kill:" + keyValuePair.Value + ":" + keyValuePair.Key); } catch (Exception ex) { Log.WriteLog(ex); throw; } } } } var f = new FBase.MainForm(); f.DoScale(); Application.Run(f); } catch (Exception ex) { Log.WriteLog(ex); throw; } } [DllImport("coredll.Dll")] private static extern int GetLastError(); [DllImport("coredll.Dll")] private static extern int ReleaseMutex(IntPtr hMutex); [DllImport("coredll.Dll")] public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool InitialOwner, string MutexName); [DllImport("Toolhelp.dll")] public static extern IntPtr CreateToolhelp32Snapshot(uint flags, uint processid); [DllImport("Coredll.dll")] public static extern int CloseHandle(IntPtr handle); [DllImport("Toolhelp.dll")] public static extern int Process32First(IntPtr handle, ref Processentry32 pe); [DllImport("Toolhelp.dll")] public static extern int Process32Next(IntPtr handle, ref Processentry32 pe);
全部代码
using System; using System.ComponentModel; using System.IO; using System.Linq; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using PDAClient.FBase; using System.Diagnostics; namespace PDAClient { internal static class Program { [DllImport("coredll.Dll")] private static extern int GetLastError(); [DllImport("coredll.Dll")] private static extern int ReleaseMutex(IntPtr hMutex); [DllImport("coredll.Dll")] public static extern IntPtr CreateMutex(IntPtr lpMutexAttributes, bool InitialOwner, string MutexName); [DllImport("Toolhelp.dll")] public static extern IntPtr CreateToolhelp32Snapshot(uint flags, uint processid); [DllImport("Coredll.dll")] public static extern int CloseHandle(IntPtr handle); [DllImport("Toolhelp.dll")] public static extern int Process32First(IntPtr handle, ref Processentry32 pe); [DllImport("Toolhelp.dll")] public static extern int Process32Next(IntPtr handle, ref Processentry32 pe); [StructLayout(LayoutKind.Sequential)] public class SECURITY_ATTRIBUTES { public int nLength; public int lpSecurityDescriptor; public int bInheritHandle; } private const int ERROR_ALREADY_EXISTS = 0183; /// <summary> /// 应用程序的主入口点。 /// </summary> [MTAThread] private static void Main() { try { IntPtr handle = CreateToolhelp32Snapshot((uint)SnapShotFlags.TH32CS_SNAPPROCESS, 0); var pDictionary = new Dictionary<int, string>(); var strAppName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; if ((int)handle != -1) { var pe32 = new Processentry32 { dwSize = (uint)Marshal.SizeOf(typeof(Processentry32)) }; int bMore = Process32First(handle, ref pe32); Processentry32 pe; Log.WriteLog("start:" + handle.ToString()); while (bMore == 1) { IntPtr temp = Marshal.AllocHGlobal((int)pe32.dwSize); Marshal.StructureToPtr(pe32, temp, true); pe = (Processentry32)Marshal.PtrToStructure(temp, typeof(Processentry32)); Marshal.FreeHGlobal(temp); Log.WriteLog(pe32.szExeFile + ":" + pe.th32ProcessID); pDictionary.Add((int)pe.th32ProcessID, pe.szExeFile); bMore = Process32Next(handle, ref pe32); } } var c = pDictionary.Values.ToList().Where(x => x.StartsWith(strAppName)).ToList(); var ic = c.Count; if (ic >= 2) { var p = pDictionary.Where(x => x.Value.StartsWith(strAppName)); if (MsgBoxs.ShowQMsgYes("检测到已运行该程序,是否结束上一个进程") == DialogResult.Yes) { foreach (KeyValuePair<int, string> keyValuePair in p) { try { if (p.LastOrDefault().Key == keyValuePair.Key) break; Process cProcess = Process.GetProcessById(keyValuePair.Key); cProcess.CloseMainWindow(); //cProcess.Kill();//进程异常结束会杀不死进程并且报 Win32Exception Log.WriteLog("kill:" + keyValuePair.Value + ":" + keyValuePair.Key); } catch (Exception ex) { Log.WriteLog(ex); throw; } } } } var f = new FBase.MainForm(); f.DoScale(); Application.Run(f); } catch (Exception ex) { Log.WriteLog(ex); throw; } //if (!IsExist()) //{ // var f = new FBase.MainForm(); // f.DoScale(); // Application.Run(f); //} //Application.Run(new Decode_Class.Form1()); } /// <summary> /// 判断程序是否已经运行 /// </summary> /// <returns> /// true: 程序已运行,则什么都不做 /// false: 程序未运行,则启动程序 /// </returns> public static bool IsExist() { string strAppName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; IntPtr hMutex = CreateMutex(IntPtr.Zero, true, strAppName); if (hMutex == IntPtr.Zero) throw new ApplicationException("Failure creating mutex: " + Marshal.GetLastWin32Error().ToString("X")); if (Marshal.GetLastWin32Error() == ERROR_ALREADY_EXISTS) { ReleaseMutex(hMutex); return true; } return false; } } [StructLayout(LayoutKind.Sequential)] public struct Processentry32 { public uint dwSize; public uint cntUsage; public uint th32ProcessID; public IntPtr th32DefaultHeapID; public uint th32ModuleID; public uint cntThreads; public uint th32ParentProcessID; public int pcPriClassBase; public uint dwFlags; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] //注意,此处为宽字符 public string szExeFile; public uint th32MemoryBase; public uint th32AccessKey; } public enum SnapShotFlags : uint { TH32CS_SNAPHEAPLIST = 0x00000001, TH32CS_SNAPPROCESS = 0x00000002, TH32CS_SNAPTHREAD = 0x00000004, TH32CS_SNAPMODULE = 0x00000008, TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST | TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD | TH32CS_SNAPMODULE), TH32CS_GETALLMODS = 0x80000000 } }