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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4693689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:58:53  来源:igfitidea点击:

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

c#javawindowswindows-7

提问by gMale

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 linkfrom 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++)

回答by Kate Gregory

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.

最简单的方法是根本不编写任何代码,即使这是堆栈溢出。单击开始,键入计划并选择计划任务。设置一个(单击创建任务)并在机器解锁时设置一个触发器。对于操作,让它向您发送电子邮件。

new triggernew action

新触发器新动作

Repeat for startup and when a user logs in, if you want. Done.

如果需要,在启动和用户登录时重复此操作。完毕。

回答by Joe Jordan

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. 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 (i.e. closing a laptop). Resuming seems to have a few different wParam values: PBT_APMRESUMESUSPEND, PBT_APMRESUMECRITICAL and PBT_APMRESUMEAUTOMATIC

您将要创建一个窗口并观察 WM_POWERBROADCAST 消息(http://msdn.microsoft.com/en-us/library/aa373248%28v=vs.85%29.aspx)并检查 wParam你想要的动作。例如,当系统即将进入挂起状态(即关闭膝上型电脑)时,您的窗口应该收到一个 WM_POWERBROADCAST,其中 PBT_APMSUSPEND 作为 wParam。恢复似乎有几个不同的 wParam 值:PBT_APMRESUMESUSPEND、PBT_APMRESUMECRITICAL 和 PBT_APMRESUMEAUTOMATIC

回答by Emmanuel

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();
    }

回答by Lawrence Dol

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 或手动更改,但在您的场景中,这种“噪音”应该非常低。

回答by Péter T?r?k

You could write a simple app and register it as a Windows service, to be started automatically at system startup. 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 服务,以便在系统启动时自动启动。这个应用程序可以在启动时做任何你想做的事情。如果它是一个合适的 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). Although this might be overkill. And it maybe possible to get notification about the JVM shutting down when the system is closing (but I have no concrete experience with this).

如果你更喜欢 Java,你可以通过像Tanuki这样合适的服务包装器将你的应用程序注册为服务(似乎他们有一个免费的社区许可证选项)。虽然这可能有点矫枉过正。并且可能会在系统关闭时收到有关 JVM 关闭的通知(但我对此没有具体经验)。

回答by Péter T?r?k

http://www.pinvoke.net/default.aspx/powrprof.CallNtPowerInformation- Check out the link. It has almost all win32api for all windows function. You can call power management feature directly in your windows 7 laptop. For that create a Windows Service , that will use these specific api to notify the machine state.

http://www.pinvoke.net/default.aspx/powrprof.CallNtPowerInformation- 查看链接。它具有几乎所有 windows 功能的所有 win32api。您可以直接在 Windows 7 笔记本电脑中调用电源管理功能。为此,创建一个 Windows Service ,它将使用这些特定的 api 来通知机器状态。