You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows屏幕亮度调整脚本无效:注册表已改但亮度未变求助

问题描述

环境:Windows 10 21H2 19044.1949、PowerShell 7.2.6

我编写了一个调整Windows屏幕亮度的脚本,修改注册表后值已按预期设置,但屏幕亮度并未实际改变。打开Windows设置->系统->屏幕,亮度值仍未变化;但手动修改该设置时,注册表值会相应更新。请问遗漏了什么?

脚本代码如下:

# 显示/设置亮度

param ( [parameter(Mandatory=$false)]
        [Int32]
        [ValidateRange(0,100)]
        $number = -1 
      );

  function Take-Permissions {
    # 来源:stackoverflow相关实现
    # 适用于PowerShell v4.0,需要管理员权限

    param($rootKey, $key, [System.Security.Principal.SecurityIdentifier]$sid = 'S-1-5-32-545', $recurse = $true)

    switch -regex ($rootKey) {
        'HKCU|HKEY_CURRENT_USER'    { $rootKey = 'CurrentUser' }
        'HKLM|HKEY_LOCAL_MACHINE'   { $rootKey = 'LocalMachine' }
        'HKCR|HKEY_CLASSES_ROOT'    { $rootKey = 'ClassesRoot' }
        'HKCC|HKEY_CURRENT_CONFIG'  { $rootKey = 'CurrentConfig' }
        'HKU|HKEY_USERS'            { $rootKey = 'Users' }
    }

    ### 步骤1 - 提升当前进程权限
    # 获取SeTakeOwnership、SeBackup和SeRestore权限,脚本需要管理员权限
    $import = '[DllImport("ntdll.dll")] public static extern int RtlAdjustPrivilege(ulong a, bool b, bool c, ref bool d);'
    $ntdll = Add-Type -Member $import -Name NtDll -PassThru
    $privileges = @{ SeTakeOwnership = 9; SeBackup =  17; SeRestore = 18 }
    foreach ($i in $privileges.Values) {
        $null = $ntdll::RtlAdjustPrivilege($i, 1, 0, [ref]0)
    }

    function Take-KeyPermissions {
        param($rootKey, $key, $sid, $recurse, $recurseLevel = 0)

        ### 步骤2 - 获取键的所有权 - 仅对当前键生效
        $regKey = [Microsoft.Win32.Registry]::$rootKey.OpenSubKey($key, 'ReadWriteSubTree', 'TakeOwnership')
        $acl = New-Object System.Security.AccessControl.RegistrySecurity
        $acl.SetOwner($sid)
        $regKey.SetAccessControl($acl)

        ### 步骤3 - 启用当前键从父键继承权限(不包括所有权)
        $acl.SetAccessRuleProtection($false, $false)
        $regKey.SetAccessControl($acl)

        ### 步骤4 - 仅对顶级键,修改当前键权限并传播到子键
        # 要让子键也应用权限,需要为每个子键重复步骤2-3(步骤5)
        if ($recurseLevel -eq 0) {
            $regKey = $regKey.OpenSubKey('', 'ReadWriteSubTree', 'ChangePermissions')
            $rule = New-Object System.Security.AccessControl.RegistryAccessRule($sid, 'FullControl', 'ContainerInherit', 'None', 'Allow')
            $acl.ResetAccessRule($rule)
            $regKey.SetAccessControl($acl)
        }

        ### 步骤5 - 递归对子键重复步骤2-5
        if ($recurse) {
            foreach($subKey in $regKey.OpenSubKey('').GetSubKeyNames()) {
                Take-KeyPermissions $rootKey ($key+'\'+$subKey) $sid $recurse ($recurseLevel+1)
            }
        }
    }

    Take-KeyPermissions $rootKey $key $sid $recurse
}

### 主逻辑 ###

# 获取当前活动电源计划的GUID:
$guid = (Get-CimInstance -classname Win32_PowerPlan -Namespace "root\cimv2\power" -Filter "IsActive='True'").InstanceID.tostring() 
$regex = [regex]"{(.*?)}"
$planGuid = $regex.Match($guid).groups[1].value

# 设置注册表路径值:
$regPath0="HKLM"
$regPath1=$regPath0+":"
$regPath2= "SYSTEM\CurrentControlSet\Control\Power\User\PowerSchemes\"+$planGuid+"\7516b95f-f776-4464-8c53-06167f40cc99\aded5e82-b909-4619-9949-f5d71dac0bcb"
$regPath=$regPath1+$regPath2
$regProp1="ACSettingIndex";
$regProp2="DCSettingIndex";
  
if ($number -eq -1) {
    Write-Host "当前亮度:" (Get-ItemProperty $regPath $regProp2).$regProp2
} else {
    # 初始状态下管理员没有修改该键的权限:
    $AdminGroupSid="S-1-5-32-544"
    Take-Permissions $regPath0 $regPath2 $AdminGroupSid $false

    Set-ItemProperty $regPath $regProp1 $number
    Set-ItemProperty $regPath $regProp2 $number

    # 验证新设置:
    Write-Host "亮度已设置为:" (Get-ItemProperty $regPath $regProp2).$regProp2
}
解决方法

你修改的注册表项是电源计划的持久化亮度设置,但Windows不会自动刷新这些设置到当前运行的系统中。要让亮度立即生效,需要通知系统电源设置已更改,或者直接调用系统API来调整实时亮度。

原因分析

  • 手动修改设置时,Windows设置应用会同时更新注册表、调用系统底层接口改变屏幕亮度,还会通知电源服务刷新配置。
  • 仅修改注册表只会改变电源计划的保存配置,不会触发系统实时调整,也不会同步设置界面的显示值。

修复方案

在脚本修改注册表后,添加以下操作之一:

方案1:通知电源服务刷新设置

添加以下代码到Set-ItemProperty之后:

# 重新激活当前电源计划,强制加载新配置
powercfg -setactive $planGuid

方案2:直接调用API修改实时亮度(推荐)

使用Windows的WMI接口直接调整屏幕亮度,这种方式无需修改注册表,设置后立即生效且同步设置界面。添加以下函数到脚本中,并在设置数值时调用:

function Set-ScreenBrightness {
    param([int]$Brightness)
    # 确保亮度值在0-100范围内
    $Brightness = [Math]::Clamp($Brightness, 0, 100)
    
    # 获取显示器亮度控制实例
    $monitorMethods = Get-CimInstance -Namespace root/wmi -ClassName WmiMonitorBrightnessMethods
    if ($monitorMethods) {
        # 1表示立即应用亮度设置
        $monitorMethods.WmiSetBrightness(1, $Brightness)
    }
}

然后在修改注册表后调用该函数:

Set-ScreenBrightness -Brightness $number

完整逻辑说明

  1. 保留你原有的注册表修改代码,确保电源计划的持久化配置更新
  2. 调用上述任一方案触发实时亮度调整
  3. 验证设置是否生效

这样修改后,屏幕亮度会立即变化,设置界面的数值也会同步更新。


内容的提问来源于stack exchange,提问作者jamacoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 00:30:57