Configurer la veilleuse (Night Light) de la mise à jour Windows Creators via le registre

Comment la nouvelle fonctionnalité Veilleuse (Night Light) dans Windows 10 (Pro) Creators Update peut-elle être configurée via le registre ?

J’aimerais configurer automatiquement les nouvelles installations/mises à jour lors de l’utilisation de mon outil de gestion de configuration de choix (Chef). L’inspection du système via Sysinternals Process Monitor montre une clé binaire Data mise à jour en profondeur dans HKCU\Software\Microsoft\Windows\CurrentVersion\CloudStore\Cache\DefaultAccount\$$windows.data.bluelightreduction.settings\Current, mais c’est un gros blob REG_BINARY et pas très utile.

De l’aide sur un registre différent, PowerShell, ou un autre moyen compatible avec l’automatisation pour configurer la fonctionnalité Veilleuse serait très apprécié !

Avec beaucoup d’expérimentation, j’ai réussi à plus ou moins déterminer le format de cette valeur du registre et j’ai écrit un script PowerShell pour la définir.

Testé sur 21H2

Et possiblement approprié pour les versions aussi anciennes que les mises à jour de 2019.

Function Set-BlueLightReductionSettings {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true)] [ValidateRange(0, 23)] [int]$StartHour,
        [Parameter(Mandatory=$true)] [ValidateSet(0, 15, 30, 45)] [int]$StartMinutes,
        [Parameter(Mandatory=$true)] [ValidateRange(0, 23)] [int]$EndHour,
        [Parameter(Mandatory=$true)] [ValidateSet(0, 15, 30, 45)] [int]$EndMinutes,
        [Parameter(Mandatory=$true)] [bool]$Enabled,
        [Parameter(Mandatory=$true)] [ValidateRange(1200, 6500)] [int]$NightColorTemperature
    )
    $data = (0x43, 0x42, 0x01, 0x00, 0x0A, 0x02, 0x01, 0x00, 0x2A, 0x06)
    $epochTime = [System.DateTimeOffset]::new((date)).ToUnixTimeSeconds()
    $data += $epochTime -band 0x7F -bor 0x80
    $data += ($epochTime -shr 7) -band 0x7F -bor 0x80
    $data += ($epochTime -shr 14) -band 0x7F -bor 0x80
    $data += ($epochTime -shr 21) -band 0x7F -bor 0x80
    $data += $epochTime -shr 28
    $data += (0x2A, 0x2B, 0x0E, 0x1D, 0x43, 0x42, 0x01, 0x00)
    If ($Enabled) {$data += (0x02, 0x01)}
    $data += (0xCA, 0x14, 0x0E)
    $data += $StartHour
    $data += 0x2E
    $data += $StartMinutes
    $data += (0x00, 0xCA, 0x1E, 0x0E)
    $data += $EndHour
    $data += 0x2E
    $data += $EndMinutes
    $data += (0x00, 0xCF, 0x28)
    $data += ($NightColorTemperature -band 0x3F) * 2 + 0x80
    $data += ($NightColorTemperature -shr 6)
    $data += (0xCA, 0x32, 0x00, 0xCA, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00)
    Set-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\CloudStore\Store\DefaultAccount\Current\default$windows.data.bluelightreduction.settings\windows.data.bluelightreduction.settings' -Name 'Data' -Value ([byte[]]$data) -Type Binary
}

Le format (ou plus précisément un format fonctionnel, puisque l’application Paramètres peut créer plusieurs dispositions légèrement différentes) :

  • 10 octets constants

  • L’horodatage Unix de dernière modification en secondes, transformé et réparti sur 5 octets dans ce qui est probablement un encodage à longueur variable :

  • Un octet dont les bits 0-6 sont les bits 0-6 de l’horodatage mais dont le bit 7 supérieur est toujours défini

  • Un octet dont les bits 0-6 sont les bits 7-13 de l’horodatage mais dont le bit supérieur est toujours défini

  • De même pour deux autres ensembles de 7 bits

  • Un octet final pour les bits 28-31 de l’horodatage, bit supérieur non défini

  • 8 octets constants

  • Uniquement si la planification est activée : octets constants 0x02, 0x01

  • 3 octets constants

  • L’heure de début

  • L’octet constant 0x2E (probablement un délimiteur de champ ou un type)

  • La minute de début

  • 4 octets constants

  • L’heure de fin

  • L’octet constant 0x2E à nouveau

  • 3 octets constants

  • La température de couleur nocturne en Kelvin, deux octets transformés :

  • Un octet dont le bit 0 bas est toujours non défini, les bits 1-6 sont les bits 0-5 de la température, et le bit 7 supérieur est toujours défini

  • Un octet pour le bit 6 et au-delà de la température, bit supérieur non défini

  • 10 octets constants

Testé sur 1703/1709

Et possiblement fonctionnel jusqu’aux mises à jour de 2018.

Function Set-BlueLightReductionSettings {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$true)] [ValidateRange(0, 23)] [int]$StartHour,
        [Parameter(Mandatory=$true)] [ValidateSet(0, 15, 30, 45)] [int]$StartMinutes,
        [Parameter(Mandatory=$true)] [ValidateRange(0, 23)] [int]$EndHour,
        [Parameter(Mandatory=$true)] [ValidateSet(0, 15, 30, 45)] [int]$EndMinutes,
        [Parameter(Mandatory=$true)] [bool]$Enabled,
        [Parameter(Mandatory=$true)] [ValidateRange(1200, 6500)] [int]$NightColorTemperature
    )
    $data = (2, 0, 0, 0)
    $data += [BitConverter]::GetBytes((Get-Date).ToFileTime())
    $data += (0, 0, 0, 0, 0x43, 0x42, 1, 0)
    If ($Enabled) {$data += (2, 1)}
    $data += (0xC2, 0x0A, 0x00) # Some users have reported this line necessary on 1709, was not needed originally
    $data += (0xCA, 0x14, 0x0E)
    $data += $StartHour
    $data += 0x2E
    $data += $StartMinutes
    $data += (0, 0xCA, 0x1E, 0x0E)
    $data += $EndHour
    $data += 0x2E
    $data += $EndMinutes
    $data += (0, 0xCF, 0x28)
    $tempHi = [Math]::Floor($NightColorTemperature / 64)
    $tempLo = (($NightColorTemperature - ($tempHi * 64)) * 2) + 128
    # Alternate proposed version (see edit history), possibly version-specific?: $tempLo = ($NightColorTemperature - ($tempHi * 64)) * 4
    $data += ($tempLo, $tempHi)
    $data += (0xCA, 0x32, 0, 0xCA, 0x3C, 0, 0)
    Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\$$windows.data.bluelightreduction.settings\Current' -Name 'Data' -Value ([byte[]]$data) -Type Binary
}

Utilisation

Sauvegardez le script en tant que fichier .ps1 et suivez les instructions de la section Activation des scripts du wiki du tag PowerShell. Vous pouvez ensuite importer le contenu du script par dot-sourcing :

. ./bluelightmanagement.ps1

Et ensuite utiliser la fonction similaire à un cmdlet qu’il fournit :

Set-BlueLightReductionSettings -StartHour 7 -StartMinutes 0 -EndHour 21 -EndMinutes 15 -Enabled $true -NightColorTemperature 6000

L’application Paramètres met même tout à jour (sauf le curseur de puissance/couleur) immédiatement si vous avez la page de réduction de lumière bleue ouverte quand vous exécutez la commande. Pour que le curseur voie les changements, vous devrez rouvrir l’application Paramètres.