对于windows form的应用程序, 操作系统其实在注销或者关闭的时候,会发一个WM_QueryEndSession的消息给每一个窗体,每一个窗体有一个表决的机会,返回是否退出.这个跟form 的closing 时间一样. 一旦有一个程序返回false,那么这个注销动作就取消了.默认.net 写的windows 应用程序都是表决true,就是系统注销的时候,程序自动退出. 
      
      
      
      所以你要相应系统注销这个消息, 比如提醒用户要不要退出,或者作一些记录log的操作, 在.net 中只要挂一个事件处理到Microsoft.Win32.SystemEvents.SessionEnding 这个事件上面去.你可以做一些自定义的操作.比如: 
      
      
    
 private
        
        
        
        
          void
        
        
          HookSessionEnding()
        
          private
        
        
        
        
          void
        
        
          HookSessionEnding() 
           {
          
        
        
        
          
            { 
             Microsoft.Win32.SystemEvents.SessionEnding
          
          
            +=
            Microsoft.Win32.SystemEvents.SessionEnding
          
          
            +=
          
          
             new
          
          
            Microsoft.Win32.SessionEndingEventHandler(
          
          
            this
          
          
            .OnSessionEnding);
          
          
            new
          
          
            Microsoft.Win32.SessionEndingEventHandler(
          
          
            this
          
          
            .OnSessionEnding); 
             }
            }
          
        
        
           private
        
        
        
        
          void
        
        
          OnSessionEnding(
        
        
          object
        
        
          sender,
        
        
          private
        
        
        
        
          void
        
        
          OnSessionEnding(
        
        
          object
        
        
          sender, 
           Microsoft.Win32.SessionEndingEventArgse)
          Microsoft.Win32.SessionEndingEventArgse) 
           {
          
        
        
        
          
            { 
             //
          
          
            theusersessionisending
          
          
            //
          
          
            theusersessionisending 
            //MessageBox...
//取消系统关闭 e.cancel=true
 }
          
          
            }
          
        
      
      当然也可以重载消息处理,自己处理WM_QueryEndSession 这个消息. 
      
      
      对于控制台应用程序,一般只能做到被动的接受,可以记录一下什么时候程序被关掉,是应为什么原因 
      
      
      实现方式其实就是调用系统api,有一些 SetConsole 打头的函数,用来实现 控制台应用程序的自定义,比如设置字体,颜色,窗体大小子类的. 2005 中其实对这些api做了一些包装. 这里主要是利用 SetConsoleCtrlHandler ,注册一个Handler 
      
      
      一下是vb.net 的一个框架 
      
      
    
 Module
          
          
            Module1
        
        
        
          
            Module
          
          
            Module1 
             Public
          
          
          
          
            Declare
          
          
          
          
          
            
              Function
            
            
              SetConsoleCtrlHandler
            
            
              Lib
            
            
            
            
              "
            
            
              kernel32.dll
            
            
              "
            
            
            
            
              Alias
            
            
            
            
              "
            
            
              SetConsoleCtrlHandler
            
            
              "
            
            
              (
            
            
              ByVal
            
            
              handlerRoutine
            
            
              As
            
            
              HandlerRoutine,
            
            
              ByVal
            
            
              add
            
            
              As
            
            
            
            
              Boolean
            
            
              )
            
            
              As
            
            
            
            
              Boolean
            
          
          
            Public
          
          
          
          
            Declare
          
          
          
          
          
            
              Function
            
            
              SetConsoleCtrlHandler
            
            
              Lib
            
            
            
            
              "
            
            
              kernel32.dll
            
            
              "
            
            
            
            
              Alias
            
            
            
            
              "
            
            
              SetConsoleCtrlHandler
            
            
              "
            
            
              (
            
            
              ByVal
            
            
              handlerRoutine
            
            
              As
            
            
              HandlerRoutine,
            
            
              ByVal
            
            
              add
            
            
              As
            
            
            
            
              Boolean
            
            
              )
            
            
              As
            
            
            
            
              Boolean
            
            
               Public
            
            
            
            
              Delegate
            
            
            
            
            
              
                Sub
              
              
                HandlerRoutine(
              
              
                ByVal
              
              
                type
              
              
                As
              
              
              
              
                Integer
              
              
                )
              
            
            
              Public
            
            
            
            
              Delegate
            
            
            
            
            
              
                Sub
              
              
                HandlerRoutine(
              
              
                ByVal
              
              
                type
              
              
                As
              
              
              
              
                Integer
              
              
                ) 
                 
                 Sub
                
                
                  Main()
                
              
              
              
                
                  Sub
                
                
                  Main() 
                   
                   SetConsoleCtrlHandler(
                
                
                  AddressOf
                
                
                  MyHandle,
                
                
                  True
                
                
                  )
                  SetConsoleCtrlHandler(
                
                
                  AddressOf
                
                
                  MyHandle,
                
                
                  True
                
                
                  ) 
                   Console.ReadLine()
                  Console.ReadLine() 
                   
                   EndSub
                
                
                  EndSub
                
              
              
                 
                 Public
              
              
              
              
              
                
                  Sub
                
                
                  MyHandle(
                
                
                  ByVal
                
                
                  type
                
                
                  As
                
                
                
                
                  Integer
                
                
                  )
                
              
              
                Public
              
              
              
              
              
                
                  Sub
                
                
                  MyHandle(
                
                
                  ByVal
                
                
                  type
                
                
                  As
                
                
                
                
                  Integer
                
                
                  ) 
                   '
                
                
                  控制台收到那些消息
                
                
                  '
                
                
                  控制台收到那些消息
                
                
                   '
                
                
                  0-CTLC
                
                
                
                
                  '
                
                
                  0-CTLC
                
                
                   '
                
                
                  1-CTL+Break
                
                
                
                
                  '
                
                
                  1-CTL+Break
                
                
                   '
                
                
                  2-CLOSE,可能是通过关闭close按钮也可能是直接关闭进程
                
                
                
                
                  '
                
                
                  2-CLOSE,可能是通过关闭close按钮也可能是直接关闭进程
                
                
                   '
                
                
                  3-操作系统要注销
                
                
                
                
                  '
                
                
                  3-操作系统要注销
                
                
                   '
                
                
                  4-系统要关机
                
                
                
                
                  '
                
                
                  4-系统要关机
                
                
                   
                
                
                   '
                
                
                  AddYourLog
                
                
                  '
                
                
                  AddYourLog
                
                
                   EndSub
                
                
                
                
                  EndSub
                
              
              
                 
                 EndModule
              
              
                EndModule
              
            
          
        
        
           
        
      
      
    
      3.对于windows 服务,api的话采取的是跟 console 类似的处理方式.只不过的他的状态切换更多 
      
      主要是调用一个 RegisterServiceCtrlHandler 的api
      
    


 
         
         
           
					 
					