简体   繁体   English

如何以编程方式检测操作系统(Windows)何时唤醒或进入睡眠状态

[英]How to programmatically detect when the OS (Windows) is waking up or going to sleep

Background 背景

My son likes to use his laptop when he's not supposed to and I just thought it would be handy if I could write an application that would email me whenever he opened / closed his laptop. 我的儿子喜欢在他不应该使用他的笔记本电脑时,我只是觉得如果我能写一个应用程序,只要他打开/关闭他的笔记本电脑就会给我发电子邮件,这会很方便。

(I'd even settle for something that notified me when there was network traffic on the machine) (我甚至会满足于在机器上有网络流量时通知我的事情)

Question

How do you programmatically detect when an OS is waking up or going to sleep? 如何以编程方式检测操作系统何时唤醒或进入睡眠状态? I found this link from this related post . 我在这篇 相关文章中找到了这个链接 But that covers OS X. I'm looking for the same thing for Windows 7. 但这涵盖了OS X.我正在为Windows 7寻找相同的东西。

(I'd like to do this in Java, if possible, but I'd settle for C#/C++) (如果可能的话,我想用Java做这个,但我会选择C#/ C ++)

Easiest way is not to write any code at all, even though this is stack overflow. 最简单的方法是不写任何代码,即使这是堆栈溢出。 Click Start, type Schedule and choose Scheduled Tasks. 单击开始,键入计划,然后选择计划任务。 Set one up (click Create Task) and set a Trigger when the machine is unlocked. 设置一个(单击“创建任务”)并在机器解锁时设置触发器。 For the Action, have it send you an email. 对于Action,请让它给您发送电子邮件。

新的触发器新行动

Repeat for startup and when a user logs in, if you want. 如果需要,重复启动和用户登录时。 Done. 完成。

You're going to want to create a window and watch for the WM_POWERBROADCAST message ( http://msdn.microsoft.com/en-us/library/aa373248%28v=vs.85%29.aspx ) and check the wParam for your desired action. 您将要创建一个窗口并观察WM_POWERBROADCAST消息( http://msdn.microsoft.com/en-us/library/aa373248%28v=vs.85%29.aspx )并检查wParam你想要的行动。 For example, your window should receive a WM_POWERBROADCAST with PBT_APMSUSPEND as the wParam when the system is about to enter a suspended state (ie closing a laptop). 例如,当系统即将进入挂起状态(即关闭笔记本电脑)时,窗口应该收到带有PBT_APMSUSPEND的WM_POWERBROADCAST作为wParam。 Resuming seems to have a few different wParam values: PBT_APMRESUMESUSPEND, PBT_APMRESUMECRITICAL and PBT_APMRESUMEAUTOMATIC 恢复似乎有几个不同的wParam值:PBT_APMRESUMESUSPEND,PBT_APMRESUMECRITICAL和PBT_APMRESUMEAUTOMATIC

I search for a long time and found that this was the best way, the 'Sleep'-event was never working before: 我搜索了很长时间,发现这是最好的方式,'睡眠'事件以前从未工作过:

 private ManagementEventWatcher managementEventWatcher;
    private readonly Dictionary<string, string> powerValues = new Dictionary<string, string>
                         {
                             {"4", "Entering Suspend"},
                             {"7", "Resume from Suspend"},
                             {"10", "Power Status Change"},
                             {"11", "OEM Event"},
                             {"18", "Resume Automatic"}
                         };
    public void InitPowerEvents()
    {
        var q = new WqlEventQuery();
        var scope = new ManagementScope("root\\CIMV2");

        q.EventClassName = "Win32_PowerManagementEvent";
        managementEventWatcher = new ManagementEventWatcher(scope, q);
        managementEventWatcher.EventArrived += PowerEventArrive;
        managementEventWatcher.Start();
    }
    private void PowerEventArrive(object sender, EventArrivedEventArgs e)
    {
        foreach (PropertyData pd in e.NewEvent.Properties)
        {
            if (pd == null || pd.Value == null) continue;
            var name = powerValues.ContainsKey(pd.Value.ToString())
                           ? powerValues[pd.Value.ToString()]
                           : pd.Value.ToString();
            Console.WriteLine("PowerEvent:"+name);
        }
    }
    public void Stop()
    {
        managementEventWatcher.Stop();
    }

A very simple, perhaps crude, but effective way may be to have a program with a timer firing every minute. 一个非常简单,也许粗糙但有效的方法可能是让程序每分钟都有一个计时器。 If the timer fires and it's been, say, 5 minutes of real time since its last execution then you can likely assume that the computer was sleeping since it's unlikely that your thread was unable to be scheduled for so long. 如果计时器触发并且比如上次执行后的5分钟实时,那么您可能会认为计算机正在睡眠,因为您的线程不太可能无法安排这么长时间。

The other reason for the difference may be a clock adjustment, like DST or a manual change, but that kind of "noise" should be very low, in your scenario. 差异的另一个原因可能是时钟调整,如DST或手动更改,但在您的方案中,这种“噪音”应该非常低。

You could write a simple app and register it as a Windows service, to be started automatically at system startup. 您可以编写一个简单的应用程序并将其注册为Windows服务,以便在系统启动时自动启动。 This app could then do whatever you want when it starts. 这个应用程序可以在它启动时做任何你想做的事情。 And if it's a proper Windows app, it can register to get notification about impending system shutdown too (I don't remember the details but I implemented this in a C++ MFC app many years ago). 如果它是一个合适的Windows应用程序,它可以注册以获得有关即将发生的系统关闭的通知(我不记得详细信息,但我多年前在C ++ MFC应用程序中实现了这一点)。

If you prefer Java, you could register your app as a service via a suitable service wrapper like Tanuki (it seems they have a free Community License option). 如果你更喜欢Java,你可以通过像Tanuki这样的合适的服务包装器将你的应用程序注册为服务(似乎他们有免费的社区许可证选项)。 Although this might be overkill. 虽然这可能有点过头了。 And it may be possible to get notification about the JVM shutting down when the system is closing (but I have no concrete experience with this). 并且有可能在系统关闭时获得关于JVM关闭的通知(但我没有具体的经验)。

http://www.pinvoke.net/default.aspx/powrprof.CallNtPowerInformation - Check out the link. http://www.pinvoke.net/default.aspx/powrprof.CallNtPowerInformation - 查看链接。 It has almost all win32api for all windows function. 它几乎都具有所有windows功能的win32api。 You can call power management feature directly in your windows 7 laptop. 您可以直接在Windows 7笔记本电脑中调用电源管理功能。 For that create a Windows Service , that will use these specific api to notify the machine state. 为此创建一个Windows服务,它将使用这些特定的api来通知机器状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM