Click here to Skip to main content
15,907,910 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,
I have to code a program to detect windows vista's standby/hibernate operation and do some custom actions (close particular application, ask user some questions...).
I read an article say that we can not do it. But some say we can use SetThreadExecutionState to do the job. I write it like this:


using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace zTestWinForm
{
    public partial class Form1 : Form
    {
        [DllImport("Kernel32.dll")]
        public static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);

        public Form1()
        {
            InitializeComponent();
        }

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            // Power status event triggered
            if (m.Msg == (int)WindowMessage.WM_POWERBROADCAST)
            {
	        // prevent sleep/hibernate
	        SetThreadExecutionState(
                            EXECUTION_STATE.ES_CONTINUOUS |
                            EXECUTION_STATE.ES_DISPLAY_REQUIRED |
                            EXECUTION_STATE.ES_SYSTEM_REQUIRED |
                            EXECUTION_STATE.ES_AWAYMODE_REQUIRED);

                MessageBox.Show("Gotcha!!");
                Thread.Sleep(10000);

                //
                // Clear EXECUTION_STATE flags to disable away mode and allow the system to idle to sleep normally.
                //
                SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
            }

            base.WndProc(ref m);
        }
    }

    internal enum WindowMessage
    {
        WM_POWERBROADCAST = 0x218,
        PBT_APMQUERYSUSPEND = 0x0,
        PBT_APMQUERYSTANDBY = 0x0001,
        BROADCAST_QUERY_DENY = 0x424D5144,
        PBT_APMSUSPEND = 0x4,
    }

    public enum EXECUTION_STATE :uint
    {
        ES_AWAYMODE_REQUIRED = 0x00000040,
        ES_CONTINUOUS = 0x80000000,
        ES_DISPLAY_REQUIRED = 0x00000002,
        ES_SYSTEM_REQUIRED = 0x00000001,
        ES_USER_PRESENT = 0x00000004,
    }
}


but it is not work. Anyone knows what's wrong with my code? Thanks a lot.
Posted

Hello Nijboer,

I modified the code as follow:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace zTestWindowsForms
{
    public partial class Form1 : Form
    {
        internal const UInt32 SE_PRIVILEGE_ENABLED = 0x00000002;
        internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
        internal const int TOKEN_QUERY = 0x8;
        internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";

        [DllImport("Kernel32.dll")]
        public static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);

        // Use this signature if you do not want the previous state
        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
           [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
           ref TOKEN_PRIVILEGES NewState,
           UInt32 Zero,
           IntPtr Null1,
           IntPtr Null2);

        [DllImport("advapi32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

        [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid);

        public Form1()
        {
            InitializeComponent();
            GetPrivilege();
        }

        private static void GetPrivilege()
        {
            // Get the current process token handle so we can get shutdown privilege. 
            IntPtr processHandle = Process.GetCurrentProcess().Handle;
            IntPtr tokenHandle;
            if (OpenProcessToken(processHandle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out tokenHandle))
            {
                // Get the LUID for shutdown privilege. 
                LUID luid = new LUID();
                LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, out luid);

                TOKEN_PRIVILEGES tkp = new TOKEN_PRIVILEGES();       // pointer to token structure 
                tkp.PrivilegeCount = 1;  // one privilege to set    
                tkp.Luid = luid;
                tkp.Attributes = SE_PRIVILEGE_ENABLED;

                // Get shutdown privilege for this process. 
                bool b = AdjustTokenPrivileges(tokenHandle, false, ref tkp, 0, IntPtr.Zero, IntPtr.Zero);

                int result = Marshal.GetLastWin32Error();
                MessageBox.Show("result = " + result);
            }
        }

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            // Power status event triggered
            if (m.Msg == (int)WindowMessage.WM_POWERBROADCAST)
            {
                // prevent sleep/hibernate
                SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_DISPLAY_REQUIRED | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);

                MessageBox.Show("Gotcha!!");
                Thread.Sleep(10000);

                //
                // Clear EXECUTION_STATE flags to disable away mode and allow the system to idle to sleep normally.
                //
                SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
            }

            base.WndProc(ref m);
        }
    }

    internal enum WindowMessage
    {
        WM_POWERBROADCAST = 0x218,
        PBT_APMQUERYSUSPEND = 0x0,
        PBT_APMQUERYSTANDBY = 0x0001,
        BROADCAST_QUERY_DENY = 0x424D5144,
        PBT_APMSUSPEND = 0x4,
    }

    public enum EXECUTION_STATE : uint
    {
        ES_AWAYMODE_REQUIRED = 0x00000040,
        ES_CONTINUOUS = 0x80000000,
        ES_DISPLAY_REQUIRED = 0x00000002,
        ES_SYSTEM_REQUIRED = 0x00000001,
        ES_USER_PRESENT = 0x00000004,
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct TOKEN_PRIVILEGES
    {
        public UInt32 PrivilegeCount;
        public LUID Luid;
        public UInt32 Attributes;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct LUID
    {
        public uint LowPart;
        public int HighPart;
    }
}


but the result are the same.
 
Share this answer
 
Comments
E.F. Nijboer 14-Jul-10 9:23am    
I guess this would only work for shutdown/restart (Only not in the way implemented now because the shutdown events are different.)

About blocking the hibernate/sleep/standby state I see in your initial call that you call the SetThreadExecutionState when the event fires. I guess the problem is that this is a bit late and I guess you should set the thread state right at the beginning of your application start up. Maybe give it a try? I am very interested in the results. Good luck!
I guess nobody can help you because this feature isn't available anymore since Vista. It is quite logical because more and more people are using netbooks and laptops and when the batery is low the system must be able to hibernate or sleep to make sure nothing is lost. The scheduled command can be ignored but if the user gives the command to sleep, shutdown or whatever, the system will execute this even if your application is trying to stall it. You just have some time to store your application state or shutdown and otherwise forced to stop. If you really want to disable these commands you should, like a virus would do, change the system configuration in a way that hibernation is not possible anymore, disable sleep mode, etc...

The question here is, what are you going to create that really needs this? Why do you want to take away control from the user? If it should run unharmed the system should simply be locked away. The question you want answered is a bit like, "how can I prevent a user from unplugging the pc?". You know the answer to that I guess and your question is now becoming just like that. But good luck finding a more satisfying answer...

MSDN information:
http://msdn.microsoft.com/en-us/library/aa372716(v=VS.85).aspx[^]

Next time you could of course search the codeproject site also...
Handling OS events like Sleep, Stand-by, Hibernate, Power Status Changed, Low Battery, Critial Suspend, AC Power, Battery Power, Battery Life etc... in Windows XP and Vista.[^]
 
Share this answer
 
v2
I guess you don't have the right privilege. You need to get this first. There also are a few changes for Vista but it should still be possible (and also is!!! There are applications that do this)

Some msdn links that should help:
http://msdn.microsoft.com/en-us/library/aa376861(VS.85).aspx[^]

http://msdn.microsoft.com/en-us/library/bb394721(v=VS.85).aspx[^]

Good luck!
 
Share this answer
 
Nobody can help me? :(
It seems that the method I used above works just with scheduled sleep/hibernate, means when user leave his computer for a period of time and it thinks it needs to sleep, then the code above will work. But if the user really wants to force it to sleep immediately, then it is not work.
The problem is out there in the Internet, but not the solution :(
 
Share this answer
 
Our clients use Windows Vista and realize that when some specific applications open a file on network (file server) and then the computer go to sleep, then when it wake up the application cannot access the file anymore OR when it is sleep, other computer cannot open the network file. That's why I have to do this. I want to remind user to close that kind of application and regardless they answer or not, the system is still go to sleep.
 
Share this answer
 
Comments
E.F. Nijboer 22-Jul-10 12:39pm    
Then users should simply be aware that the application is closing all of the open network files when explicitly going into hibernation or sleep mode. You get some time to do this and notify the user that the files are closed because of the action they took. There wouldn't really be any need to leave a file open when leaving the pc because it disturbs other users in accessing files. They simply should be aware that they are not alone and cannot simply hog the file :)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900