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

System Events (SessionEnding) not working as expected

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

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


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


代码

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 并且事件正在响应。但是我假设 运行 形成一个循环,所以我想知道在哪里放置我自己的逻辑(在这个例子中是 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 永远不会创建(意味着循环本身永远不会执行)

编辑2: 我已经在 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
}

Windows 处理事件的应用程序使用消息循环。 在您的代码中,您没有 运行 消息循环。

添加到Main方法:

Application.Run();

This 为您的应用启动消息循环。