C#中各類結束進程的方法

 

Process類的CloseMainWindow, Kill, Close:

1.Process.CloseMainWindow是GUI程序的最友好結束方式,從名字上就能夠看出來它是經過關閉程序主窗體,至關於用戶點擊窗體的關閉按鈕或者按Alt + F4。它的本質就是向主窗體發送WM_CLOSE消息(Process.MainWindowsHandle能夠返回主窗體的句柄)。這個能夠在.NET Framework源代碼中看出來框架

public bool CloseMainWindow()ide

{函數

    IntPtr mainWindowHandle = this.MainWindowHandle;ui

    //句柄是否爲0this

    if (mainWindowHandle == IntPtr.Zero)spa

    {操作系統

        return false;.net

    }線程

    //GetWindowLong是否成功執行orm

    if ((NativeMethods.GetWindowLong(new HandleRef(this, mainWindowHandle), -16) &0x8000000) != 0)

    {

        return false;

    }

    //0x10 是 WM_CLOSE消息

    //向主窗體發送WM_CLOSE,注意是PostMessage而不是SendMessage

    NativeMethods.PostMessage(new HandleRef(this, mainWindowHandle), 0x10, IntPtr.Zero,IntPtr.Zero);

    return true;

}

    CloseMainWindow方法使用PostMessage(不是SendMessage,因此消息會加在消息隊列的最後)方法向主窗體發送一個WM_CLOSE消息,這樣等主窗體處理完全部消息後,等遇到WM_CLOSE便開始執行退出動做。

  好比記事本接到了WM_CLOSE消息可是有未保存的文件,記事本會彈出對話框提示用戶保存仍是不保存仍是取消退出操做。Windows Forms和WPF的窗體都會有相似操做,經過窗體的Closing事件來在WM_CLOSE消息接收後作出是否退出的決定。

 

 

以後咱們會講到Windows Forms和WPF都有本身的友好型常規退出方式,可是其實有一個通用的GUI程序退出方式,就是利用這個CloseMainWindow方法:

//Windows Forms和WPF均可以用

//Windows Forms的Form.Closing事件會在以後發生

//WPF的Windows.Closing事件也會

Process.GetCurrentProcess().CloseMainWindow();

 

 

2.接下來就是Process.Kill方法,從名字也能夠看出來,直接殺掉,不給任何喘息機會呵呵。Kill方法會直接結束整個進程,不進行常規資源清理(什麼finally塊等……)。Kill本質調用本地API:TerminateProcess函數。

 

 

3.最後一個是Process.Close方法。抱歉它根本不是用來結束進程的!這個方法名字有些誤導,其實則否則。它僅僅是IDisposable的Dispose方法的具體執行,用來進行Process類的託管資源清理的!

因爲Process類繼承自Component類,後者繼承IDisposable而同時又有析構函數,而經過一個繼承類可改寫的Dispose方法(參數是bool disposing)來判斷這個Dispose是用戶調用仍是GC調用。而這個Process.Close()方法正是用戶調用Dispose時進行託管資源的清理方法:

下面Process.Dispose方法代碼:

protected override void Dispose(bool disposing)

{

    if (!this.disposed)

    {

        if (disposing)

        {

            //用戶調用,清理託管資源

            this.Close();

        }

        this.disposed = true;

        //調用Component的Dispose

        base.Dispose(disposing);

    }

}

  可見這個Close方法相似不少其餘.NET中的類的Close,好比Stream……所以Close確定不會結束進程,僅僅是Process類做爲IDisposable接口的間接繼承者的自我清理方法。

Environment類的Exit和FailFast

 1. Environment.Exit至關於在Main函數中的return指令。不過它不會執行代碼塊的finally塊(若是有的話),但資源清理仍是要進行的。

  它是最多見的退出當前進程的方法之一。在Main函數中咱們能夠直接return語句便退出了程序。若是不在Main函數內,那麼Environment.Exit方法就能夠派上用場

class a

{

    ~a()

    {

        Console.WriteLine("析構函數");

    }

}

class Program

{

    static void Main()

    {

        try

        {

            a oa = new a();

            test();

        }

        finally

        {

            //這段代碼永遠不會執行

            Console.WriteLine("finally");

        }

    }

 

    static void test()

    {

        Environment.Exit(0);

    }

}

代碼將會輸出:

析構函數

看來GC調用了oa的析構函數,但注意finally塊沒有運行。

 

 

 2.Environment.FailFast方法更速度,它甚至不須要向操做系統返回進程退出代碼(ExitCode),直接結束當前進程並在應用程序事件薄中寫入信息,用於程序出現致命錯誤須要當即中止。

class a

{

    ~a()

    {

        Console.WriteLine("析構函數");

    }

}

class Program

{

    static void Main()

    {

        try

        {

            a oa = new a();

            Environment.FailFast("致命錯誤發生!");

        }

        finally

        {

            //這段代碼永遠不會執行

            Console.WriteLine("finally");

        }

    }

}

在.NET 4.0下,Environment.FailFast代碼會拋出FatalExecutionEngineError,而在4.0以前會拋出ExecutionEngineException。但都不會有任何輸出(GC沒有清理對象,同時finally塊也沒有運行)

 

WPF的Shutdown和Windows Forms的Exit

  GUI程序每每都有本身的消息隊列和事件管理模式,所以結束一個GUI程序要遠複雜與結束一個控制檯程序。上述的方法中,Process.Kill和Environment.Exit和FailFast若是用在一個GUI程序中,都會直接強制結束整個程序,而不會激發GUI窗體的一些針對應用程序結束的事件(好比Closing事件)。而上面也講過:Process.CloseMainWindow經過向主窗體發送一個WM_CLOSE消息能夠很好的結束一個GUI程序,不過每每更天然的方法是利用GUI框架自己提供的結束程序的方法。

 

WPF中是System.Windows.Application.Shutdown方法,它其實就是在當前線程的消息隊列Dispatcher對象中加入一個正常優先級(DispatcherPriority.Normal)的回調退出函數,等消息隊列最後處理到該項時程序開始退出操做。一般這樣使用:

//或者App也能夠,WPF程序默認會有一個App類繼承Application類

Application.Current.Shutdown();

Windows Forms中是:System.Windows.Forms.Application.Exit方法。它是經過Application.OpenFormsInternal屬性先把已經打開的窗體經過正常方式都關閉(運行Form.Closing事件),最後再結束整個應用程序進程。

最後,經過WPF的Window.Closing或Windows Forms的Form.Closing事件均可以取消這種形式的退出操做。??

非託管的ExitProcess和TerminateProcess

這是Windows API中結束進程的非託管方法。ExitProcess結束進程更友好些,而TerminateProcess會當即強制結束進程。二者的關係有點像Environment.Exit和FailFast,但我不肯定本質上是否同樣。並且TerminateProcess能夠指定進程返回值,但FailFast不能夠。兩個非託管API的執行都不回運行finally塊。

 

使用起來很簡單(關鍵是P/Invoke,參考:http://www.pinvoke.net,頗有用的)

 

using System.Runtime.InteropServices;

class Program

{

    [DllImport("kernel32.dll")]

    static extern void ExitProcess(uint uExitCode);

 

    [DllImport("kernel32.dll", SetLastError = true)]

    [return: MarshalAs(UnmanagedType.Bool)]

    static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);

 

    static void Main()

    {

        ExitProcess(1);

        //或者

        TerminateProcess(Process.GetCurrentProcess().Handle, 1);

    }

}

 

手動發送WM_CLOSE,WM_DESTROY,WM_QUIT消息

在一個GUI程序運行環境下,咱們經過獲得窗體的句柄,而後即可以向該句柄發送消息,WndProc(Window Procedure)函數會處理相應的事件。其中WM_CLOSE至關於用戶點擊關閉按鈕,使用PostMessage將WM_CLOSE發送至主窗體等價於.NET中Process類的CloseMainWindow方法,當接收到WM_CLOSE消息時,應用程序是能夠選擇是否真正結束程序的,若是繼續結束程序而不取消。接着WM_DESTROY消息會發送,這個消息表明着窗體開始真正關閉,此時能夠進行一些資源的清理。最後當前線程接收到WM_QUIT消息,線程的消息循環會被終止。

 

所以向窗體發送這3個消息,只有WM_CLOSE會引起Closing事件,屬於正常窗體退出邏輯,其餘兩個中消息會直接強行關閉窗體。

注意WM_QUIT消息只能用PostMessage將其送至消息隊列尾部,使用SendMessage當即發送在WPF應用程序上運行後程序沒有任何反應。

 

下面是一個WPF程序發送下列消息,(並無貼XAML,你必定知道怎樣加3個按鈕而後把Click事件和窗體的Closing事件綁在代碼上吧)(一下部分不瞭解,由於不知道WPF和XAML)

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Data;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Imaging;

using System.Windows.Navigation;

using System.Windows.Shapes;

//外加命名空間

using System.Diagnostics;

using System.Runtime.InteropServices;

 

namespace Mgen.TEX

{

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

        }

 

        //Windows消息值

        const uint WM_CLOSE = 0x10;

        const uint WM_DESTROY = 0x02;

        const uint WM_QUIT = 0x12;

 

        //SendMessage和PostMessage的P/Invoke

        [DllImport("user32.dll", CharSet = CharSet.Auto)]

        static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtrlParam);

 

        [return: MarshalAs(UnmanagedType.Bool)]

        [DllImport("user32.dll", SetLastError = true)]

        static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

 

        //窗體的Closing事件,判斷Closing是否被運行

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)

        {

            MessageBox.Show("Closing事件!");

        }

 

        //發送三種消息

        private void WM_CLOSE_Click(object sender, RoutedEventArgs e)

        {

            //也能夠用PostMessage

            SendMessage(Process.GetCurrentProcess().MainWindowHandle, WM_CLOSE, IntPtr.Zero,IntPtr.Zero);

        }

 

        private void WM_DESTROY_Click(object sender, RoutedEventArgs e)

        {

            //也能夠用PostMessage

            SendMessage(Process.GetCurrentProcess().MainWindowHandle, WM_DESTROY,IntPtr.Zero, IntPtr.Zero);

        }

 

        private void WM_QUIT_Click(object sender, RoutedEventArgs e)

        {

            //只能使用PostMessage去將WM_QUIT送至消息隊列尾部

            PostMessage(Process.GetCurrentProcess().MainWindowHandle, WM_QUIT, IntPtr.Zero,IntPtr.Zero);

        }

 

    }

}

相關文章
相關標籤/搜索