Automatically sets your Windows desktop wallpaper to a base image with a countdown text rendered on top, updating daily until a target date. The app runs silently in the background via Windows Task Scheduler.
- Downloads a fresh base image and config daily from your GitHub repository.
- Renders a customizable countdown text (with shadow and semi-transparent background) onto the image.
- Sets the rendered image as the Windows desktop wallpaper.
- Runs silently — no visible PowerShell window.
- Task Scheduler integration:
- Daily at a configured time (default
00:30). - At every user logon.
- Starts when available (catches up if the PC was off).
- Runs on battery.
- Daily at a configured time (default
- Modular architecture with full Pester test coverage.
- When the countdown reaches zero or below, the app displays an uninstall reminder.
- Windows 10 / 11
- PowerShell 5.1+ (or PowerShell 7 with Windows compatibility)
- .NET Framework (for
System.Drawing) - Internet access (for initial install and daily config/image sync from GitHub)
- Fork this repository, open new branch for each event and push your customizations (see Configuration below).
- Download or use
release/install.exe. - Run
install.exeas Administrator.
The installer will:
- Download the repository ZIP from GitHub into
%APPDATA%\.wallpaper_countdown. - Load
Src/config.jsonand register a Windows Scheduled Task (ChangeWallpaperEveryDay) that runsSrc/daily_run.ps1silently viaSrc/run_hidden.vbs. - Run
daily_run.ps1immediately so the wallpaper is updated right away.
Edit Src/config.json before pushing to GitHub (the installer will pick it up automatically, and the daily run will keep it in sync):
{
"system": {
"taskName": "ChangeWallpaperEveryDay",
"appFolder": ".wallpaper_countdown"
},
"github": {
"username": "YourGitHubUsername",
"repository": "YourRepoName",
"branch": "main",
"imagePath": "backgrounds/1.jpg"
},
"wallpaper": {
"targetDate": "2026-12-31",
"text": "...עוד {days} ימים",
"time": "00:30"
}
}| Key | Description |
|---|---|
system.taskName |
Name of the Windows Scheduled Task. |
system.appFolder |
Folder name under %APPDATA% used for local storage. |
github.username |
Your GitHub username (owner of the fork). Automatically updates when pushed |
github.repository |
Repository name. Automatically updates when pushed |
github.branch |
Branch to pull config and image from. Automatically updates when pushed |
github.imagePath |
Relative path to the base wallpaper image in the repo. Changes take effect on the next daily run. |
wallpaper.targetDate |
The target countdown date (YYYY-MM-DD). |
wallpaper.text |
Text rendered on the wallpaper. Use {days} as a placeholder for the day count. |
wallpaper.time |
Daily trigger time for the Scheduled Task (HH:mm). |
Note: GitHub Actions workflows automatically run on push:
.github/workflows/auto-update-config.ymlkeepsSrc/config.jsonandSrc/install.ps1aligned with the current GitHub context..github/workflows/build-exe.ymlbuildsinstall.exeanduninstall.exe, then updatesrelease/*.exe.
- Install —
install.ps1downloads the repo ZIP, extracts it to%APPDATA%\.wallpaper_countdown, registers the scheduled task, and runs the first daily update. - Daily run —
Src/daily_run.ps1orchestrates each update:- Polls
Src/config.jsonfrom GitHub to stay in sync with any config changes you push. - Downloads the latest base image from
github.imagePath. - Computes the number of days remaining until
wallpaper.targetDate. - If days remaining ≤ 0: prints a completion message prompting you to run
uninstall.exe. - Otherwise: renders the countdown text onto the image using GDI+ (
System.Drawing) and sets it as the desktop wallpaper viaSystemParametersInfo.
- Polls
- Silent execution —
Src/run_hidden.vbslaunchesdaily_run.ps1viawscript.exewith window style0(hidden), so no console window appears.
| Module | Responsibility |
|---|---|
Src/Modules/Logging.psm1 |
File-based structured logging (Initialize-Logging, Write-Log). |
Src/Modules/Config.psm1 |
Reads and validates config.json (Get-Config). |
Src/Modules/Downloads.psm1 |
Polls remote config and images from GitHub with cache-busting headers (Get-RemoteBaseUrl, Poll-RemoteConfig, Poll-Img). |
Src/Modules/Countdown.psm1 |
Calculates days remaining and formats the display text (Get-DaysRemaining, Get-DaysText). |
Src/Modules/Image.psm1 |
Renders text overlay onto the base image and saves a JPEG (Export-CountdownImage). |
Src/Modules/System.psm1 |
Sets the desktop wallpaper via the Windows API (Set-Wallpaper). |
Run uninstall.exe (or Src/uninstall.ps1) as Administrator. The uninstaller will:
- Clear the desktop wallpaper (set to black / blank).
- Remove the Windows Scheduled Task.
- Delete the
%APPDATA%\.wallpaper_countdownfolder.
If the countdown has already reached zero, the daily run will print a reminder with the path to
uninstall.exe.
Install Pester v5 and run:
Import-Module Pester -RequiredVersion 5.7.1 -Force
Invoke-Pester .\Tests$config = New-PesterConfiguration
$config.Run.Path = ".\Tests"
$config.CodeCoverage.Enabled = $true
$config.CodeCoverage.Path = ".\Src\Modules\*.psm1"
$config.CodeCoverage.OutputFormat = "JaCoCo"
$config.CodeCoverage.OutputPath = ".\coverage.xml"
Invoke-Pester -Configuration $configreportgenerator `
-reports:coverage.xml `
-targetdir:coverage-report `
-sourcedirs:Src\ModulesEXE files are built automatically on push events that modify Src/install.ps1 by .github/workflows/build-exe.yml.
The workflow:
- builds
install.exeanduninstall.exeonwindows-latest. - commits them into
release/install.exeandrelease/uninstall.exe. - uploads them as GitHub Actions artifacts (
exes-<branch>-<sha>).
If you want to build locally, install the ps2exe module, then:
Invoke-ps2exe .\Src\install.ps1 .\install.exe `
-noConsole `
-requireAdmin `
-iconFile .\Src\icons\install.ico `
-title "Wallpaper Installer" `
-description "Installs wallpaper automation"
Invoke-ps2exe .\Src\uninstall.ps1 .\uninstall.exe `
-noConsole `
-requireAdmin `
-iconFile .\Src\icons\uninstall.ico `
-title "Wallpaper Uninstaller" `
-description "Uninstalls wallpaper automation"