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
}
}
