How to change Windows 10 theme automatically?

How to make windows go dark at night and light in the morning. Monitor brightness and theme automation apps. Theme change with Powershell.

Never thought I was going to need this, but recently my worktime span across the whole day and I always found myself struggling with white in dark and with dark during the day.

I set up all apps to "Use system theme" - the only thing I was missing - is actually an automatic switcher for Windows. Sure, I can just go to the settings and adjust the theme every time, but I decided to get acquainted with Powershell and automate this in 1 simple script to get some new knowledge.

Navigate the table of contents to setup Windows 10 theme auto change or learn how it was built:

Building a script

When automating something to happen at logon or certain time on Windows, it makes sense to use scheduler. And if you open it (just put scheduler in win search) - you will see many apps already using it a lot for their chores.

image.png

What we need is to create tasks firing in these cases:

  1. Evening time
  2. Morning time
  3. User logon

These can be 3 separate tasks but to ease the management, let's go with 1 script called in each of those cases.
Script will follow this logic when called:

  1. Check current time -> enable corresponding theme
  2. Copy itself into specified folder (I picked User folder)
  3. Register scheduler task to call this script from that folder

How to switch dark / light themes in Windows?

First of all we need to know how to actually switch the themes. Luckily for us its just a matter of 2 variables in registry: AppsUseLightTheme and SystemUsesLightTheme, their names are self-explanatory. We are going to set this variables in registry from 1 to 0 and vise versa so we save commands to variables (of course you can do it yourself manually as well)

$enable_light_apps = 'reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize /v AppsUseLightTheme /t REG_DWORD /d 1 /f'
$enable_light_system  = 'reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize /v SystemUsesLightTheme /t REG_DWORD /d 1 /f'
$enable_dark_apps = 'reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize /v AppsUseLightTheme /t REG_DWORD /d 0 /f'
$enable_dark_system  = 'reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize /v SystemUsesLightTheme /t REG_DWORD /d 0 /f'

How to detect and react on current time?

For our simple purposes we will edit the script directly before launch, setting up the time. In this implementation only hours are supported. We convert received time to [int], compare and invoke our "switcher" functions specified before.

[int]$lighttime = 7
[int]$nighttime = 19

[int]$hrs = Get-Date -Format HH

Write-host "Day boundaries: $lighttime - $nighttime"

if ($hrs -ge $lighttime -and $hrs -lt $nighttime) {
  Write-Host "Its a day time!"
  Invoke-Expression $enable_light_apps
  Invoke-Expression $enable_light_system
} else {
  Write-Host "Its a night time!"
  Invoke-Expression $enable_dark_apps
  Invoke-Expression $enable_dark_system
}

How to create a scheduled task?

There are easy ways using SCHTASKS:

SCHTASKS /CREATE /SC DAILY /TN "Switch To Dark Theme" /TR "reg add HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize /v AppsUseLightTheme /t REG_DWORD /d 0 /f" /ST 19:00 /F

But it allows only 1 trigger and 1 action specified. Otherwise, you have to use a separate XML file for that. That's why we will go with a more flexible option - PowerShell itself.

In SCHTASKS example we specified /F key meaning we want to overwrite any task that is already created. That's needed to quickly update the task if we want to change time, etc. To do the same in PowerShell we need to handle this separately:

function Delete-ScheduledTask([string] $taskName)
{
    Write-Host "Delete schedule task for $taskName"
    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
}


function DeleteIfExists-ScheduledTask([string] $taskName)
{
    $exists = Get-ScheduledTask | Where-Object {$_.TaskName -like $taskName}
    if($exists)
    {
        Delete-ScheduledTask $taskName
    }
}

Then we create triggers we need (note usage of user_name - we can omit it so the task runs for ALL users, but in that case, it will require elevation:

$user_name = [environment]::username

$trigger = @(
    $(New-ScheduledTaskTrigger -At "$([string]$lighttime):00" -Daily),
    $(New-ScheduledTaskTrigger -At "$([string]$nighttime):00" -Daily)
    $(New-ScheduledTaskTrigger -AtLogOn -User $user_name)
)

Last thing is to define the task name and action, and register (owerwrite) the task:

$task_name = "Theme Switcher"
DeleteIfExists-ScheduledTask($task_name)

$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy Bypass -File $script_destination_file"
Register-ScheduledTask -TaskName $task_name -Trigger $trigger -Action

How do we install the script?

Well, you could copy the script manually, but to speed things up - we just self-copy it to the desired location if it called not from there:

[string]$user_folder = $env:USERPROFILE
if ($PSScriptRoot -ne $user_folder) {
    $MyInvocation.MyCommand.ScriptContents | Out-File $script_destination_file
}

Final solution

Just download and save with .ps1 extension and run from command line or right click - "Run with powershell". In case running scripts is disabled use this form:

powershell -ExecutionPolicy Bypass -File C:\Users\lflse\Desktop\script.ps1

Here is raw link as Hasnode seems buggy 😢 Raw download

Apps to use

Dark Reader extension

Its highly configurable extension to make all websites go dark. It can listen to system theme change if configured (Download): image.png

Auto Dark Mode

After I developed this I found other solution to the problem with nice GUI and more options - in case you are okay with having more apps on PC: Auto Dark Mode

App is following same principles - just instead of triggering script it triggers itself and registers more tasks instead of 1 with 3 triggers.:

image.png

Monitorian

Another app to look at - in case you have multiple screens you can control their brightness with ease and windows-style UI: Monitorian


Thanks for reading! My articles are constantly revised and updated, so bookmark if you want to be up-to-date on a topic 🍺

No Comments Yet