如何在Windows Vista中阻止/取消待机/休眠操作
问题描述:
我必须编写一个程序来检测Windows Vista的待机/休眠操作并执行一些自定义操作(关闭特定的应用程序,向用户询问一些问题...).
我读过一篇文章,说我们做不到.但是有人说我们可以使用SetThreadExecutionState来完成这项工作.我这样写:
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.
答
Hello Nijboer,
我将代码修改如下:
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.
我想没人能帮助您,因为自Vista以来该功能不再可用.这是很合乎逻辑的,因为越来越多的人正在使用上网本和笔记本电脑,并且当电池电量低时,系统必须能够休眠或睡眠以确保没有丢失任何东西.计划的命令可以忽略,但是如果用户让命令进入睡眠,关机或其他状态,即使您的应用程序试图使其停止运行,系统也会执行该命令.您只有一些时间来存储您的应用程序状态或关闭,否则将被迫停止.如果您确实想禁用这些命令,则应像病毒一样禁用系统配置,使其不再可能进入休眠状态,并禁用睡眠模式,等等.
这里的问题是,您将要创建真正需要此功能的东西吗?为什么要从用户手中夺走控制权?如果它可以正常运行,则只需将其锁定即可.您要回答的问题有点像,如何防止用户拔出PC的电源?".您知道答案,我想您的问题现在正变得如此.但是祝您找到更满意的答案...
MSDN信息:
http://msdn.microsoft.com/en-us/library/aa372716 (v = VS.85).aspx [处理操作系统事件,例如睡眠,待机,休眠,电源状态已更改,电池电量低,严重挂起, Windows XP和Vista中的交流电源,电池电源,电池寿命等. [ ^ ]
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.[^]
我想您没有适当的权限.您需要先获得它. Vista也有一些更改,但仍然应该可行(而且!!!!!!!!!!!!!!).
一些应该帮助的msdn链接:
http://msdn.microsoft.com/en-us/library/aa376861(VS .85).aspx [ ^ ]
http://msdn.microsoft.com/en-us/library/bb394721 (v = VS.85).aspx [
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!