【问题标题】:how can I turn off 'allow hybrid sleep' in advanced power setting? by c#如何在高级电源设置中关闭“允许混合睡眠”?由 c#
【发布时间】:2013-05-30 00:20:46
【问题描述】:

如何在高级电源设置中关闭“允许混合睡眠”?由 c# 手动:电源选项->更改计划设置->更改高级电源设置-> 睡眠->“允许混合睡眠”-> 插入:关闭

【问题讨论】:

  • 请记住,“混合睡眠”在 Windows 7 中只是“睡眠”。
  • @Polynomial,你确定吗?我使用的是 win7 操作系统,所以它似乎是“允许混合睡眠”
  • 是的,电源选项在那里,但是当您真正点击“睡眠”按钮时,它会根据该电源选项进行正常或混合睡眠。
  • 最好使用组策略来完成

标签: c#


【解决方案1】:

如果您的目标是 Windows 7/2008 Server,那么您可以使用 WMI 和 Win32_PowerSetting 类。下面是执行此操作的代码。确保将程序集引用和using 指令添加到System.Management

    private bool SetAllowHybridSleep(bool enabled)
    {
        //Machine to work on, "." for local
        string RemotePC = ".";

        //Set the namespace to the power namespace, used throughout the function
        ManagementScope ms = new ManagementScope(@"\\" + RemotePC + @"\root\cimv2\power");

        //Will hold each of our queries
        ObjectQuery oq = null;

        //Will hold the values of our power plan and the specific setting that we want to change
        Guid PowerPlanInstanceId = Guid.Empty;
        string PowerSettingInstanceId = null;

        //Look for the specific setting that we want
        oq = new ObjectQuery(string.Format("SELECT * FROM Win32_PowerSetting WHERE ElementName = 'Allow hybrid sleep'"));
        using (ManagementObjectSearcher mos = new ManagementObjectSearcher(ms, oq))
        {
            ManagementObjectCollection results = mos.Get();
            foreach (ManagementObject obj in results)
            {
                foreach (PropertyData p in obj.Properties)
                {
                    if (p.Name == "InstanceID")
                    {
                        //This will give us a string with a GUID specific to our setting
                        PowerSettingInstanceId = p.Value.ToString();
                        break;
                    }
                }
            }
        }

        //Sanity check
        if (string.IsNullOrEmpty(PowerSettingInstanceId))
        {
            Console.WriteLine("System does not support hybrid sleep");
            return false;
        }

        //Look for the active power scheme
        oq = new ObjectQuery("SELECT * FROM Win32_PowerPlan WHERE IsActive=True");
        using (ManagementObjectSearcher mos = new ManagementObjectSearcher(ms, oq))
        {
            ManagementObjectCollection results = mos.Get();
            foreach (ManagementObject obj in results)
            {
                foreach (PropertyData p in obj.Properties)
                {
                    if (p.Name == "InstanceID")
                    {
                        //The instance contains a string with a GUID inside of it, use the code below to get the GUID by itself
                        if (!Guid.TryParse(System.Text.RegularExpressions.Regex.Match(p.Value.ToString(), @"\{[0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12}\}").Value, out PowerPlanInstanceId))
                        {
                            Console.WriteLine("Could not find active power plan");
                            return false;
                        }
                        break;
                    }
                }
            }
        }

        //Now we need to update the actual power setting in the active plan
        //Get all power schemes for the target setting
        oq = new ObjectQuery(string.Format("ASSOCIATORS OF {{Win32_PowerSetting.InstanceID=\"{0}\"}} WHERE ResultClass = Win32_PowerSettingDataIndex", PowerSettingInstanceId.Replace(@"\", @"\\")));
        using (ManagementObjectSearcher mos = new ManagementObjectSearcher(ms, oq))
        {
            ManagementObjectCollection results = mos.Get();
            foreach (ManagementObject obj in results)
            {
                foreach (PropertyData p in obj.Properties)
                {
                    //See if the current scheme is the current setting. This will happen twice, once for AC and once for DC
                    if (p.Name == "InstanceID" && p.Value.ToString().Contains(PowerPlanInstanceId.ToString()))
                    {
                        //Change the value of the current setting
                        obj.SetPropertyValue("SettingIndexValue", (enabled ? "1" : "0"));
                        obj.Put();
                        break;
                    }
                }
            }
        }

        return true;
    }

【讨论】:

    【解决方案2】:

    使用 procmon,我设法确定以下注册表项在我的机器上负责它。

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\238C9FA8-0AAD-41ED-83F4-97BE242C8F20\94ac6d29-73ce-41a6-809f-6363ba21b47e

    您可能需要对您的机器进行一些研究,看看它是如何为您工作的。

    您也可以调用 powercfg 实用程序来执行此操作。每个电源设置都由三项标识:

    1. 电源配置文件的 GUID
    2. 配置文件子组的 GUID
    3. 设置的 GUID

    您可以使用powercfg -QUERY 生成完整的值列表。

    获得要编辑的配置文件的 GUID、子组的 GUID(在本例中为睡眠子组)和设置的 GUID(允许混合睡眠)后,您可以使用powercfg -SETACVALUEINDEX插入或powercfg -SETDCVALUEINDEX 使用电池来设置值。

    在我的情况下(Win7 Ultimate x64),您可以使用以下命令将其关闭:
    powercfg -SETACVALUEINDEX 381b4222-f694-41f0-9685-ff5bb260df2e 238c9fa8-0aad-41ed-83f4-97be242c8f20 94ac6d29-73ce-41a6-809f-6363ba21b47e 1

    这将转换为以下中的 AcSettingIndex 值:
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\238C9FA8-0AAD-41ED-83F4-97BE242C8F20\94AC6D29-73CE-41A6-809F-6363BA21B47E\DefaultPowerSchemeValues\381b4222-f694-41f0-9685-ff5bb260df2e

    【讨论】:

    • 无论如何,操作注册表项或使用 powercfg 都可以。
    • 电源管理 API 是解决问题的正确方法,但组策略听起来更有效
    • @DavidHeffernan - 我倾向于对所有内容进行逆向工程;)
    • @DavidHeffernan - 当然。我还没有接触过电源管理 API,所以我想我会弄清楚控制面板和 powercfg 是如何做到的。愿意发布一个详细说明如何使用电源管理 API 的答案吗?
    • 很高兴我得到了一些帮助:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-07
    • 2016-02-20
    • 2019-05-02
    • 2019-03-06
    • 1970-01-01
    相关资源
    最近更新 更多