none
Detect if machine shutdown has started RRS feed

  • Question

  • The OS has a Win32 function: GetSystemMetrics, if we call this with flag code = 0x2000 we can (in effect) ask Windows if a system (machine) shutdown is underway.

    I need to do this from managed code, I can of course call GetSystemMetrics but I wondered if there is managed way to do this already (.Net 3.5).

    I have read that Environment.HasShutdownStarted is not related to or connected with a machine shutting down, but just an AppDomain, so this is no use to me.

    Thanks

    Cap'n
    Wednesday, February 17, 2010 9:11 PM

All replies

  • Handle the Microsoft.Win32.SystemEvents.SessionEnding event.
    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser
    Wednesday, February 17, 2010 9:21 PM
    Moderator
  • Handle the Microsoft.Win32.SystemEvents.SessionEnding event.
    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser

    Hi I cant really do that David.

    The managed library is designed for use in any setting, windows, console, service, asp.net etc etc.

    I dont want to be told when a shutdown is issued I want to be able to ask at any instant in time if one has been issued.

    Thanks

    Cap'n

    Wednesday, February 17, 2010 9:32 PM
  • Wrap it.  Get a little creative.

    public static class ShutdownDetector
    {
        public static bool ShutdownHasStarted { get; set; }

        static ShutdownDetector()
        {
             ShutdownHasStarted = false;
             SystemEvents.SessionEnding += OnShutdownStarted;
        }

        private static OnShutdownStarted(object sender, SessionEndingEventArgs e)
        {
             ShutdownHasStarted = true;
        }
    }

    Usage:

    if (ShutdownDetector.ShutdownHasStarted)
    {
        // whatever.
    }

    Of course, this could cause problems if a shutdown starts, but is cancelled. 


    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser
    Wednesday, February 17, 2010 9:37 PM
    Moderator
  • Wrap it.  Get a little creative.

    public static class ShutdownDetector
    {
        public static bool ShutdownHasStarted { get; set; }

        static ShutdownDetector()
        {
             ShutdownHasStarted = false;
             SystemEvents.SessionEnding += OnShutdownStarted;
        }

        private static OnShutdownStarted(object sender, SessionEndingEventArgs e)
        {
             ShutdownHasStarted = true;
        }
    }

    Usage:

    if (ShutdownDetector.ShutdownHasStarted)
    {
        // whatever.
    }

    Of course, this could cause problems if a shutdown starts, but is cancelled. 


    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiLinkedInForumsBrowser

    Hmm I like that idea.

    It seems the handler is invoked in the context of a dedicated system event thread, so this will work genrically whatever sort of code is running.

    Thanks for this, I never really looked at SystemEvents before nor was I aware of that dedicated thread.

    Thanks

    Cap'n

    Ooopss I spoke to soon.

    I misread the docs, it seems the event requires a message pump (lame when there is a dedicated thread).

    So this wont work.

    Cap'n

    • Edited by Captain Kernel Wednesday, February 17, 2010 10:13 PM clarify
    Wednesday, February 17, 2010 10:08 PM
  • > it seems the event requires a message pump

    Fortunately this can be worked around with minimal impact on the rest of your program.  See below.  (You will need to add a reference to System.Windows.Forms, however.)

    using System;
    using System.Data;
    using System.Linq;
    using System.Text.RegularExpressions;
    using System.Threading;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Thread td = new Thread(ThreadProc);
                td.IsBackground = true;
                td.SetApartmentState(ApartmentState.STA);
                td.Start();
    
                Microsoft.Win32.SystemEvents.SessionEnding += HandleSessionEnding;
            }
    
            private static void ThreadProc()
            {
                System.Windows.Forms.Application.Run();
            }
    
            private static void HandleSessionEnding(object sender, Microsoft.Win32.SessionEndingEventArgs e)
            {
                //...
            }
        }
    }
    
    Thursday, February 18, 2010 12:40 AM
  • > it seems the event requires a message pump

    Fortunately this can be worked around with minimal impact on the rest of your program.  See below.  (You will need to add a reference to System.Windows.Forms, however.)

    using System;
    
    using System.Data;
    
    using System.Linq;
    
    using System.Text.RegularExpressions;
    
    using System.Threading;
    
    
    
    namespace ConsoleApplication1
    
    {
    
        class Program
    
        {
    
            static void Main(string[] args)
    
            {
    
                Thread td = new Thread(ThreadProc);
    
                td.IsBackground = true;
    
                td.SetApartmentState(ApartmentState.STA);
    
                td.Start();
    
    
    
                Microsoft.Win32.SystemEvents.SessionEnding += HandleSessionEnding;
    
            }
    
    
    
            private static void ThreadProc()
    
            {
    
                System.Windows.Forms.Application.Run();
    
            }
    
    
    
            private static void HandleSessionEnding(object sender, Microsoft.Win32.SessionEndingEventArgs e)
    
            {
    
                //...
    
            }
    
        }
    
    }
    
    
    
    


    Thanks for this and the other suggestions, having pondered these I am of the opinion that a simple static wrapper around the Win32 GetSystemMetrics (with arg 0x2000) will be better and has no dependency on message pump threads or anything.

    I am a little puzzled as to why MS have not provided a set of system events that are usable easily right out of the box in any kind of app, be it windows, service, console etc.

    I worked on an OS once (Stratus VOS) that provided system events as just that, real OS events, you could attach to and wait on these just as you can use events in any ordinary setting.

    Things like shutdown, start_process and so on were all supported and it was very easy to use.

    Anyway, thanks again for your suggestions.

    Cap'n


    Thursday, February 18, 2010 12:58 PM
  • Wrap it.  Get a little creative.

    public static class ShutdownDetector
    {
        public static bool ShutdownHasStarted { get; set; }

        static ShutdownDetector()
        {
             ShutdownHasStarted = false;
             SystemEvents.SessionEnding += OnShutdownStarted;
        }

        private static OnShutdownStarted(object sender, SessionEndingEventArgs e)
        {
             ShutdownHasStarted = true;
        }
    }

    Usage:

    if (ShutdownDetector.ShutdownHasStarted)
    {
        // whatever.
    }

    Of corse, this could cause problems if a shutdown starts, but is cancelled. 


    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light Wiki LinkedInForumsBrowser

    Thanks very much! There is something about the sample I cannot understand, Any examples for reference?
    Sunday, August 22, 2010 1:27 AM