Today’s cheap trick is a little script you can use to schedule your Windows dark/light themes by the time of day.

Even though *.theme, *.themepack, and *.deskthemepack files from all those years ago are still supported, Microsoft hasn’t provided a way to switch themes silently from a command line since the Plus! Pack Desktop Themes were replaced by the direct shell integration for themes. You’ll notice these file types no longer carry an “Apply” verb in their context menu, and launching them will open up your system theme settings (either Control Panel in Windows XP-8, or Settings in Windows 10-11).

In the old days when these files had the apply verb, you could open a theme file with a command line switch that applied it without showing any UI. Of course this was GDI days and worlds apart from how applications are styled and themed today, but it was a great way to add variety to your desktop. The old Plus! Theme Manager even had an option to rotate the theme monthly, which it accommodated by simply scheduling a recurring task in the Windows Task Scheduler:

These still work, check out my themes page to get these and other themes for Windows.

It just so happens that in modern versions of Windows, it is possible to programmatically trigger the light & dark mode from PowerShell using a simple one-line command. Type or paste this into a PowerShell window to switch your system (Taskbar, Start menu, etc.) to use light theme:

New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" -Name "SystemUsesLightTheme" -Value 1 -PropertyType DWORD -Force

And type this to set your apps (and File Explorer) to use light theme:

New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" -Name "AppsUseLightTheme" -Value 1 -PropertyType DWORD -Force

In both cases you can swap the value to a 0 (zero) to invoke dark mode instead.

Together with a super convenient Set-Wallpaper function from Jose Espitia, it’s actually not too hard to schedule entire theme changes (wallpaper and colors) based on the hour of the day! So I put together a short script to do it. It has 3 options:

  • Dark Hour (from which hour of the day should Windows be dark?)
  • Dark Wallpaper (the wallpaper picture file you want during dark hours)
  • Light Wallpaper (the wallpaper picture file you want during light hours)

When this script runs, it checks the current time and then applies the light mode/wallpaper if the hour has not yet been reached, or dark mode if that hour of the day has arrived.

Since it won’t actually do anything if the values are already set, you could set this script to run every 15 minutes or hourly, but my suggestion would be to just set it to run twice a day, sometime shortly after your dark hour. For example if I want dark mode to activate after 7pm, I’d schedule this script to run at perhaps 7:05 AM and 7:05 PM. When the script runs at 7:05 PM, it will “notice” the hour is at least 19 and change the system to dark mode.

Note that Windows can take up to 60 seconds to finish applying the color mode, during which time the system will lag considerably. So the recommendation I would make, use the Task Scheduler option to only run the task if the machine is idle idle so that the lag of theme switching isn’t disruptive to an active user, and have it wait for idle so that if you stop interacting with your machine for a period of time, the theme will get applied.

Basically this means that at 7:05 PM — or the first time my machine is idle for at least 60 seconds after that time, the theme will switch.

Setting it up

The steps to setup this script are pretty straightforward and easy!

  1. Copy the script below and paste into Notepad, saving it as ThemeSwitch.ps1 in a folder of your choice.
  2. Customize the Dark Hour and Wallpaper options near the top of the script.
  3. Create a Scheduled Task to run this script as described/illustrated above and in the script.
<#

PowerShell Theme Switch
By Shawn Keene - 29-SEPT-2021

Sets your Windows OS light/dark mode and wallpaper based on the time of day when script runs.
Adjust the 3 variables at the top as desired, then schedule this command to run with Windows Task Scheduler:

Program: C:\Windows\System32\cmd.exe
Arguments: /c start /min powershell.exe -executionpolicy bypass -file "C:\Path\ThemeSwitch.ps1"


Set the task to run a few seconds/minutes after the dark hour. Or set a recurrence so this runs every 15 minutes, since it won't have any effect if the system is already in the set state.

Task Scheduler recommendation: only run if machine is idle so that the lag of theme switching isn't disruptive to an active user.

#>

$DarkHour = 19   #Switch to dark mode after this hour of the day (19 = 7 PM local time)
$DarkWallpaper = "C:\Windows\Web\Wallpaper\Windows\img19.jpg"
$LightWallpaper = "C:\Windows\Web\Wallpaper\Windows\img0.jpg"


# Nothing to edit below unless you want to :)
$currentHour = (Get-Date).Hour
$themePath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"

Function Set-WallPaper {
<#
    Jose Espitia September 15, 2017
    Set-Wallpaper Powershell Function
    https://www.joseespitia.com/2017/09/15/set-wallpaper-powershell-function/

    .SYNOPSIS
    Applies a specified wallpaper to the current user's desktop

    .PARAMETER Image
    Provide the exact path to the image
 
    .PARAMETER Style
    Provide wallpaper style (Example: Fill, Fit, Stretch, Tile, Center, or Span)
  
    .EXAMPLE
    Set-WallPaper -Image "C:\Wallpaper\Default.jpg"
    Set-WallPaper -Image "C:\Wallpaper\Background.jpg" -Style Fit
#>
 
param (
    [parameter(Mandatory=$True)]
    # Provide path to image
    [string]$Image,
    # Provide wallpaper style that you would like applied
    [parameter(Mandatory=$False)]
    [ValidateSet('Fill', 'Fit', 'Stretch', 'Tile', 'Center', 'Span')]
    [string]$Style
)
 
$WallpaperStyle = Switch ($Style) {
    "Fill" {"10"}
    "Fit" {"6"}
    "Stretch" {"2"}
    "Tile" {"0"}
    "Center" {"0"}
    "Span" {"22"}  
}
 
If($Style -eq "Tile") {
 
    New-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name WallpaperStyle -PropertyType String -Value $WallpaperStyle -Force
    New-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name TileWallpaper -PropertyType String -Value 1 -Force
 
}
Else {
 
    New-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name WallpaperStyle -PropertyType String -Value $WallpaperStyle -Force
    New-ItemProperty -Path "HKCU:\Control Panel\Desktop" -Name TileWallpaper -PropertyType String -Value 0 -Force
 
}
 
Add-Type -TypeDefinition @" 
using System; 
using System.Runtime.InteropServices;
  
public class Params
{ 
    [DllImport("User32.dll",CharSet=CharSet.Unicode)] 
    public static extern int SystemParametersInfo (Int32 uAction, 
                                                   Int32 uParam, 
                                                   String lpvParam, 
                                                   Int32 fuWinIni);
}
"@ 
  
    $SPI_SETDESKWALLPAPER = 0x0014
    $UpdateIniFile = 0x01
    $SendChangeEvent = 0x02
  
    $fWinIni = $UpdateIniFile -bor $SendChangeEvent
  
    $ret = [Params]::SystemParametersInfo($SPI_SETDESKWALLPAPER, 0, $Image, $fWinIni)
}

# If we're in the dark hour or later, switch to dark mode.
if ( $currentHour -ge $DarkHour )
{
    if ( Test-Path $themePath )
    {
        New-ItemProperty -Path $themePath -Name "SystemUsesLightTheme" -Value 0 -PropertyType DWORD -Force | Out-Null
        New-ItemProperty -Path $themePath -Name "AppsUseLightTheme" -Value 0 -PropertyType DWORD -Force | Out-Null
    }
    Set-WallPaper -Image $DarkWallpaper -Style Fill
}

# If we're before the dark hour, switch to light mode.
if ( $currentHour -lt $DarkHour )
{
    if ( Test-Path $themePath )
    {
        New-ItemProperty -Path $themePath -Name "SystemUsesLightTheme" -Value 1 -PropertyType DWORD -Force | Out-Null
        New-ItemProperty -Path $themePath -Name "AppsUseLightTheme" -Value 1 -PropertyType DWORD -Force | Out-Null
    }
    Set-WallPaper -Image $LightWallpaper -Style Fill
}

This could easily be modified to two shortcuts on your desktop (or hot key strokes) to switch themes on-demand, but I like the elegance of a scheduled task.

Taking the easy way out

If you prefer a ready to use program that does all this for you, try out WinDynamicDesktop. It’s available from the Microsoft App Store or GitHub, and provides for downloading additional day/night themes and scheduling their application. Some even have multiple images that shift throughout the entire day.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.