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);

        }

 

    }

}

相关文章
相关标签/搜索