只要动手就能学到东西6 小功能却很麻烦

众所周知windows可以设置过某一段时间,比如 10分钟,如果没有动键盘或鼠标,就关闭屏幕。屏幕关闭后,动一下鼠标,又会亮起来,但是要好几秒钟(笔记本通过扩展坞和显示器连接,大概是这个原因),不耐烦,设成永不关闭。但是,下班了,不用电脑,一直开着屏幕白白浪费电,也不好,需要还原设置。但这样老是手工切换太麻烦了,于是想写个小程序来控制。

想到windows的设置一般能在注册表里找到。但这个设置花了很多时间,查了不少资料才找到(windows 10):HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes\8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c\7516b95f-f776-4464-8c53-06167f40cc99\3c0bc021-c8a8-4e07-a973-6b14cbcb2b7e,把这个键下面的ACSettingIndex值设成0就是永不关闭,600就是10分钟,其余类推。下次如果忘了这个键,或者需要改别的休眠选项,可以先搜DisplayOffTimeoutPluggedIn(如果是用电池,搜DisplayOffTimeoutOnBattery,其余可见HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\default\Power下的键值),然后看键值RegKeyPathRedirect的值,通常为Software\Policies\Microsoft\Power\PowerSettings\3c0bc021-c8a8-4e07-a973-6b14cbcb2b7e,然后在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes\下搜3c0bc021-c8a8-4e07-a973-6b14cbcb2b7e,就找到了。

但这个键值不能直接改,提示无权限,需要先将该键的所有者改为自己(管理员),注意一定要勾选Replace owner on subcontainers and objects这个选项,然后把权限设成Full Control。

接下来写个控制台程序,看似很简单:

        static void Main(string[] args)
        {
            RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes\8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c\7516b95f-f776-4464-8c53-06167f40cc99\3c0bc021-c8a8-4e07-a973-6b14cbcb2b7e", true);
            if (DateTime.Now.Hour < 17)
            {
                key.SetValue("ACSettingIndex", 0);
            }
            else
            {
                key.SetValue("ACSettingIndex", 600);
            }
        }

但运行时出错,提示无权限(windows 10系统下)。查了资料,原来要在项目中加一个app.manifest文件:

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>
</asmv1:assembly>

然后在windows的计划任务中添加一个任务,设置两个trigger(因为一天要运行两次)一个定在9:00,一个定在17:00,把action设成那个控制台程序。试运行出错,提示无法启动。查了资料,把运行的用户改成System,就正常了。

但是,虽然注册表是改了,在windows桌面打开屏幕关闭时间的设置,确实也改了,但是屏幕却无法关闭。看来,光改注册表还不行。

最后才查到正确的方法,是用windows api:

[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
        static extern UInt32 PowerGetActiveScheme(IntPtr UserPowerKey, out IntPtr ActivePolicyGuid);

        [DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
        static extern UInt32 PowerWriteACValueIndex(IntPtr RootPowerKey,
            [MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
            [MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
            [MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
            int AcValueIndex);

        [DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
        static extern UInt32 PowerSetActiveScheme(IntPtr RootPowerKey,
            [MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid);

        static readonly Guid GUID_DISPLAY_SETTINGS_SUBGROUP = new Guid("7516b95f-f776-4464-8c53-06167f40cc99");
        static readonly Guid GUID_DISPLAYIDLETIMEOUT = new Guid("3c0bc021-c8a8-4e07-a973-6b14cbcb2b7e");

          static void Main(string[] args)
          {

              int idleTime = DateTime.Now.Hour < 17 ? 0 : 600;

            IntPtr pActiveSchemeGuid;
            var hr = PowerGetActiveScheme(IntPtr.Zero, out pActiveSchemeGuid);
            Guid activeSchemeGuid = (Guid)Marshal.PtrToStructure(pActiveSchemeGuid, typeof(Guid));

            hr = PowerWriteACValueIndex(
                 IntPtr.Zero,
                 activeSchemeGuid,
                 GUID_DISPLAY_SETTINGS_SUBGROUP,
                 GUID_DISPLAYIDLETIMEOUT,
                 idleTime);

            PowerSetActiveScheme(IntPtr.Zero, activeSchemeGuid);
}

 

很小的功能,实现起来却很麻烦。当然,也算学到点东西,增加一点经验。只要动手就能学到东西。

posted @ 2021-06-23 00:22  平静寄居者  阅读(108)  评论(0编辑  收藏  举报