-
Notifications
You must be signed in to change notification settings - Fork 1
/
Rotate-Desktop-Background.ps1
executable file
·193 lines (158 loc) · 5.64 KB
/
Rotate-Desktop-Background.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
#Requires -Version 2
<#
.SYNOPSIS
Sets the desktop background to a randomly chosen image out of a pool of
images.
.DESCRIPTION
Sets the desktop background to a randomly chosen image out of a pool of
images. Optionally, you can use different pools of images, dependent on the
date (useful for having Christmas desktop backgrounds appear only in
December, for example). A pool will go through each of its images one time
and then start over. Pool usage history is saved in an XML file in the same
folder as this script. Intended to be run as a scheduled task.
.INPUTS
None. You cannot pipe objects to this script.
.OUTPUTS
None. This script does not generate any output.
.LINK
https://github.com/ataylor32/windows-desktop-background-rotator
#>
[CmdletBinding()]
Param()
# Define the functions for each pool of images.
Function Get-Default-Pool {
Get-ChildItem "$([Environment]::GetFolderPath(`"MyPictures`"))\Desktop Backgrounds" -Recurse
}
# Define which dates should use a pool other than the default pool.
$Dates = @()
# Determine which pool to use based on today's date.
$PoolToUse = "Default"
$Today = (Get-Date)
$ThisYearIsALeapYear = [System.DateTime]::IsLeapYear($Today.Year)
ForEach ($DateData In $Dates) {
If (
$ThisYearIsALeapYear -Eq $False -And (
$DateData.StartDate -Eq "02-29" -Or
$DateData.EndDate -Eq "02-29"
)
) {
If ($DateData.StartDate -Eq "02-29" -And $DateData.EndDate -Eq "02-29") {
# The user is probably intending to have this pool used only if the
# date is exactly February 29th.
Continue
}
If ($DateData.StartDate -Eq "02-29") {
$DateData.StartDate = "02-28"
}
Else {
$DateData.EndDate = "02-28"
}
}
$StartDate = [DateTime]"$($Today.Year)-$($DateData.StartDate)"
$EndDate = [DateTime]"$($Today.Year)-$($DateData.EndDate) 11:59:59 PM"
If ($Today -Ge $StartDate -And $Today -Le $EndDate) {
$PoolToUse = $DateData.Pool
Break
}
}
Write-Verbose "Pool that will be used: $PoolToUse"
# Get the pool, remove any non-images from it, and shuffle it.
$FunctionName = "Get-$($PoolToUse)-Pool"
Try {
$Pool = Invoke-Expression $FunctionName
}
Catch [System.Management.Automation.CommandNotFoundException] {
Throw "The `"$FunctionName`" function does not exist"
}
If ($Pool -Eq $Null) {
Throw "The `"$FunctionName`" function returned null"
}
$Pool = $Pool | Where-Object {".bmp", ".gif", ".jpeg", ".jpg", ".png" -Eq $_.Extension}
If ($Pool -Eq $Null) {
Throw "The `"$FunctionName`" function did not return any images"
}
Write-Verbose "Total images in the pool: $($Pool.Length)"
$Pool = $Pool | Sort-Object {Get-Random}
# Pick an unused image out of the pool. If every image in the pool has
# already been used, reset the usage history for the pool. Once an image
# has been picked, save it to the pool's usage history.
$XMLPath = (Split-Path $SCRIPT:MyInvocation.MyCommand.Path -Parent) + "\Rotate-Desktop-Background.xml"
Try {
$PoolUsages = Import-Clixml $XMLPath
}
Catch {
$PoolUsages = @{}
}
If ($PoolUsages.ContainsKey($PoolToUse) -Eq $False) {
$PoolUsages.Add($PoolToUse, @())
}
ForEach ($Image In $Pool) {
If ($PoolUsages.$PoolToUse -NotContains $Image.FullName) {
$ImageToUse = $Image
Break
}
}
If ($ImageToUse -Eq $Null) {
Write-Verbose "All of the images in the `"$PoolToUse`" pool have already been used. Starting over."
$PoolUsages.$PoolToUse = @()
$ImageToUse = $Pool | Get-Random
}
Write-Verbose "Image that will be used: $($ImageToUse.FullName)"
$PoolUsages.$PoolToUse += $ImageToUse.FullName
$PoolUsages | Export-Clixml $XMLPath
# If the image is in a format that Windows does not handle natively,
# convert it to a JPEG.
If (@(".bmp", ".jpeg", ".jpg") -NotContains $ImageToUse.Extension) {
[Void][Reflection.Assembly]::LoadWithPartialName("System.Drawing")
$JPGPath = [System.IO.Path]::GetTempPath() + [Guid]::NewGuid() + ".jpg"
Write-Verbose "Converting the image to JPEG format, saving to `"$JPGPath`""
$Image = [System.Drawing.Image]::FromFile($($ImageToUse.FullName))
$Image.Save($JPGPath, [System.Drawing.Imaging.ImageFormat]::Jpeg)
$Image.Dispose()
$ImageToUse = Get-ChildItem $JPGPath
}
# Set the image as the desktop background using the code from
# http://stackoverflow.com/a/9440226
Add-Type @"
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Wallpaper
{
public enum Style : int
{
Tile, Center, Stretch, NoChange
}
public class Setter {
public const int SetDesktopWallpaper = 20;
public const int UpdateIniFile = 0x01;
public const int SendWinIniChange = 0x02;
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int SystemParametersInfo (int uAction, int uParam, string lpvParam, int fuWinIni);
public static void SetWallpaper ( string path, Wallpaper.Style style ) {
SystemParametersInfo( SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange );
RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
switch( style )
{
case Style.Stretch :
key.SetValue(@"WallpaperStyle", "2") ;
key.SetValue(@"TileWallpaper", "0") ;
break;
case Style.Center :
key.SetValue(@"WallpaperStyle", "1") ;
key.SetValue(@"TileWallpaper", "0") ;
break;
case Style.Tile :
key.SetValue(@"WallpaperStyle", "1") ;
key.SetValue(@"TileWallpaper", "1") ;
break;
case Style.NoChange :
break;
}
key.Close();
}
}
}
"@
Write-Verbose "Setting the image as the desktop background"
[Wallpaper.Setter]::SetWallpaper($ImageToUse.FullName, 2)