【问题标题】:How to programmatically detect when the OS (Windows) is waking up or going to sleep如何以编程方式检测操作系统(Windows)何时唤醒或进入睡眠状态
【发布时间】:2011-06-09 06:50:22
【问题描述】:

背景

我儿子喜欢在他不应该使用的时候使用他的笔记本电脑,我只是认为如果我可以编写一个应用程序,当他打开/关闭他的笔记本电脑时会向我发送电子邮件。

(我什至会接受在机器上有网络流量时通知我的东西)

问题

您如何以编程方式检测操作系统何时唤醒或进入睡眠状态?我从this related post 找到了this link。但这涵盖了 OS X。我正在为 Windows 7 寻找同样的东西。

(如果可能的话,我想在 Java 中执行此操作,但我会满足于 C#/C++)

【问题讨论】:

  • 据我所知,您无法在 Java 中执行此操作,除非您以某种方式使用 JNI 或 JNA 与操作系统绑定。
  • 您检查过 Windows 事件日志吗?我相信它包含足够的信息。
  • 听起来对家长控制很有用。我用它来防止登录太早或太晚。
  • 受我最近从事的一个项目的推动,您的问题的潜在替代解决方案是这样的。您可以编写一个简单的 C# 应用程序,该应用程序每 10-15 分钟截取一次屏幕截图并将其保存到您的 Dropbox(或通过电子邮件发送给您)。如果是作为服务安装的,在电脑睡着的时候就不起作用了,醒来的时候,你不仅会知道,还可以监控他到底在做什么。

标签: c# java windows windows-7


【解决方案1】:

我搜索了很长时间,发现这是最好的方法,'Sleep'-event 以前从未工作过:

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

【讨论】:

【解决方案2】:

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

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

【讨论】:

  • 我认为这将完全(更不用说优雅地)解决我的问题。我会尝试并报告!
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      您可以编写一个简单的应用程序并将其注册为 Windows 服务,以便在系统启动时自动启动。这个应用程序可以在它启动时做任何你想做的事情。如果它是一个合适的 Windows 应用程序,它也可以注册以获取有关即将关闭的系统的通知(我不记得细节,但我多年前在 C++ MFC 应用程序中实现了这一点)。

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

      【讨论】:

        【解决方案6】:

        一个非常简单,也许粗略但有效的方法可能是让一个程序每分钟触发一次计时器。如果计时器触发并且自上次执行以来已经有 5 分钟的实时时间,那么您可能会认为计算机正在休眠,因为您的线程不太可能无法安排这么长时间。

        造成差异的另一个原因可能是时钟调整,如 DST 或手动更改,但在您的场景中,这种“噪音”应该非常低。

        【讨论】:

        • 我不得不说,不过,Java 将消耗 大量 的内存用于如此琐碎的用途。
        猜你喜欢
        • 2010-12-06
        • 2011-02-10
        • 1970-01-01
        • 2014-09-28
        • 1970-01-01
        • 2015-09-23
        • 1970-01-01
        • 2012-08-29
        • 2011-09-08
        相关资源
        最近更新 更多