系统事件(SessionEnding)无法按预期工作

时间:2018-02-14 08:26:43

标签: c# events shutdown

我已经制作了一个简单的Windows应用程序(虽然没有任何Form),并且在我根据C#Cookbook中的recipe19.1使用SessionEnding在操作系统关闭之前做了一些事情(我修改了,因为Debug无论如何都不会工作)

应用程序在启动时创建文本文件(确实如此),然后在发生任何事件时应创建另一个空白文本文件。 代码如下,它不能按预期工作。事件发生时不会创建任何内容。有人能告诉我这有什么问题吗?

作为旁注,我这次使用WndProc的覆盖尝试了其他示例,如the documentation中所述,它似乎有效,但我不知道如何将其应用于没有表单的应用程序

代码

using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Threading;

namespace NoConsoleApp2
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {    
            RegisterForSystemEvents();
            System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "Onstart.txt");

            bool keepRunning = true;
            Debug.WriteLine("Start");
            for (int i = 0; i < 100 && keepRunning; i++)
            {
                Thread.Sleep(1000);
            }    
            Debug.WriteLine("End");
        }

        public static void RegisterForSystemEvents()
        {
            //Always get the final notification when the event thread is shutting down 
            //so we can unregister.

            SystemEvents.EventsThreadShutdown += new EventHandler(OnEventsThreadShutdown);
            SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(OnPowerModeChanged);
            SystemEvents.SessionSwitch += new SessionSwitchEventHandler(OnSessionSwitch);
            SystemEvents.SessionEnding += new SessionEndingEventHandler(OnSessionEnding);
            SystemEvents.SessionEnded += new SessionEndedEventHandler(OnSessionEnded);
        }
        private static void UnregisterFromSystemEvents()
        {
            SystemEvents.EventsThreadShutdown -= new EventHandler(OnEventsThreadShutdown);
            SystemEvents.PowerModeChanged -= new PowerModeChangedEventHandler(OnPowerModeChanged);
            SystemEvents.SessionSwitch -= new SessionSwitchEventHandler(OnSessionSwitch);
            SystemEvents.SessionEnding -= new SessionEndingEventHandler(OnSessionEnding);
            SystemEvents.SessionEnded -= new SessionEndedEventHandler(OnSessionEnded);

        }
        /* Notifies you when the thread that is distributing the events from the SystemEvents class is
         * shutting down so that we can unregister events on the SystemEvents class
         */ 
        private static void OnEventsThreadShutdown(object sender, EventArgs e)
        {
            System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "END.txt");
            Debug.WriteLine("System event thread is shutting down, no more notifications");
            //Unregister all our events as the notification thread is goin away
            UnregisterFromSystemEvents();
        }
        /* Triggers when the user suspends or resumes the system from a suspended state
         */ 
        private static void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
        {
            System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "power.txt");
            switch (e.Mode)
            {
                case PowerModes.Resume:
                    Debug.WriteLine("PowerMode: OS is resuming from suspended state");
                    break;
                case PowerModes.StatusChange:
                    Debug.WriteLine("PowerMode: There was a change relating to the power supply (weak battery, unplug, etc...)");
                    break;
                case PowerModes.Suspend:
                    Debug.WriteLine("PowerMode: OS is about to be suspended");
                    break;

            }
        }
        /* Triggered by a change in the logged-on user
         */ 
        private static void OnSessionSwitch(object sender, SessionSwitchEventArgs e)
        {
            System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "sessionswitch.txt");

            switch (e.Reason)
            {
                case SessionSwitchReason.ConsoleConnect:
                    Debug.WriteLine("Session connected from the console");
                    break;
                case SessionSwitchReason.ConsoleDisconnect:
                    Debug.WriteLine("Session disconnected from the console");
                    break;
                case SessionSwitchReason.RemoteConnect:
                    Debug.WriteLine("Remote Session connected");
                    break;
                case SessionSwitchReason.RemoteDisconnect:
                    Debug.WriteLine("Remote Session disconnected");
                    break;
                case SessionSwitchReason.SessionLock:
                    Debug.WriteLine("Session has been locked");
                    break;
                case SessionSwitchReason.SessionLogoff:
                    Debug.WriteLine("User was logged off from a session");
                    break;
                case SessionSwitchReason.SessionLogon:
                    Debug.WriteLine("User has logged on to a session");
                    break;
                case SessionSwitchReason.SessionRemoteControl:
                    Debug.WriteLine("Session changed to or from remote status");
                    break;
                case SessionSwitchReason.SessionUnlock:
                    Debug.WriteLine("Session has been unlocked");
                    break;

            }
        }
        /* Triggered when the user is trying to log off or shut down the system
         */ 
       private static void OnSessionEnding(object sender, SessionEndingEventArgs e)
        {
            System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "sessionend.txt");

            //True to cancel the user request to end the session, false otherwise
            e.Cancel =  false;

            switch(e.Reason)
            {
                case SessionEndReasons.Logoff:
                    Debug.WriteLine("Session ending as the user is logging off");
                    System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "Logoff.txt");
                    break;
                case SessionEndReasons.SystemShutdown:
                    Debug.WriteLine("Session ending as the OS is shutting down");
                    System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "Shutdown.txt");
                    break;

            }

        }
        /*  Triggered when the user is actually logging off or shutting down the system
         */ 
        private static void OnSessionEnded(object sender, SessionEndedEventArgs e )
        { 
            switch(e.Reason)
            {
                case SessionEndReasons.Logoff:
                    Debug.WriteLine("Session ended as the user is logging off");
                    System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "Loggedoff.txt");
                    break;
                case SessionEndReasons.SystemShutdown:
                    Debug.WriteLine("Session ended as the OS is shutting down");
                    System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "Shutted.txt");
                    break;
            }

        }


    }
}

编辑:

我被告知我应该使用Application.Run并且事件正在响应。但是我假设Run生成一个循环所以我想知道在哪里放置我自己的逻辑(在这个例子中是for循环)

static void Main()
{    
    RegisterForSystemEvents();
    System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "Onstart.txt");

    bool keepRunning = true;
    Debug.WriteLine("Start");

    Application.Run();  //this activates the events

    System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "GoFOrloop.txt");

    for (int i = 0; i < 100 && keepRunning; i++)
    {
        Thread.Sleep(1000);
    }    
    Debug.WriteLine("End");
}

在这种情况下,永远不会创建文件GoForLoop.txt(意味着循环本身永远不会被执行)

EDIT2: 我在EDIT中尝试了解决方案并且它可以工作(事件被触发)但是主要逻辑(在这种情况下是循环)不起作用所以我尝试了第二个建议来使用应用程序上下文。可悲的是,这次循环工作时,事件不再被触发:(

class Context : ApplicationContext
    {

        public Context()
        {
            System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "GoFOrLoop.txt");
            for (int i = 0; i < 60; i++)
            {
                //    Console.WriteLine("Number: " + i);
                Thread.Sleep(1000);
            }



            System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "end.txt");
            Debug.WriteLine("End");


            //  Environment.Exit(1);
            ExitThread();
        }



    }

并在主

 [STAThread]
        static void Main()
        {
            /*    Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
                */

            RegisterForSystemEvents();

            System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "Onstart.txt");

//            bool keepRunning = true;

            Debug.WriteLine("Start");

             //           Application.Run(); //this works
            Application.Run(new Context()); //this DOES NOT work
}

1 个答案:

答案 0 :(得分:1)

流程事件的Windows应用程序使用消息循环。 在您的代码中,您不会运行消息循环。

添加到Main方法:

Application.Run();

This为您的应用启动meessage循环。