How do I change the wallpaper slideshow album programmatically?

The operating system I am using is Windows 10. I would like to change the album for the desktop wallpaper and lock screen slideshow by using a script or other programmatic means. I've looked into changing regedit settings but I couldn't find anything in regedit that directly referenced the album directory.

So far I've looked at HKEY_CURRENT_USER\Control Panel\Desktop and found that the current wallpaper picture is stored in %APPDATA%\Microsoft\Windows\Themes\TranscodedWallpaper and the elements of the slideshow is encoded in slideshow.ini which is a hidden file in that directory.

Again I would like to find a way to change this programmatically.


Solution 1:

So...I am using Windows 7. For the moment, the following seems to be working for me:

First you want to set up the slideshow as you want it, then go and save a backup of the file

%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Themes\slideshow.ini

As far as I can tell, this encodes the album folder path. There may be a way to build your own, but at this point I don't know.

I am using powershell. My powershell does the following:

Define a function to set the wallpaper based on the code here:

Add-Type @"
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Wallpaper {

   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 lpvPara, int fuWinIni);

      public static void SetWallpaper (string path) {

         SystemParametersInfo(SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange);

         RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);

         //"Fit" style
         key.SetValue(@"WallpaperStyle", "6");
         key.SetValue(@"TileWallpaper", "0");

         key.Close();
      }
   }
}
"@

[Wallpaper.Setter]::SetWallpaper("C:\My\Cool\Pics\monkey.jpg")

The total code is probably too long, but the gist is as follows:

Set Wallpaper from Picture to Slideshow

  1. Set the Wallpaper path to "" using the above function
  2. Copy the backed up slideshow.ini file back into that directory
  3. Stop-process -name explorer
  4. Sleep 1 sec, and start up explorer only if it hasn't automatically restarted

Set Wallpaper From Slideshow to Single Picture

  1. Delete the following two files if they exist:
    ~\AppData\Roaming\Microsoft\Windows\Themes\slideshow.ini
    ~\AppData\Roaming\Microsoft\Windows\Themes\TranscodedImage.jpg
  1. Set the wallpaper path using the above function
  2. Stop-process -name explorer
  3. Sleep 1 sec, and start up explorer only if it hasn't automatically restarted

Regarding the encoding of the slideshow.ini file: according to this forum conversation, the encoded field is a "uuencoded PCIDLIST_ABSOLUTE struct". I haven't looked into this but maybe someone can figure out how to create them.

Regarding killing explorer. It takes a few seconds on my machine for explorer to start up the slideshow after restarting but as far as I can tell it seems to work consistently. I've tried several alternatives but I couldn't figure out a cleaner way to make the desktop refresh and grab the new settings. I can see in SysInternals procmon when explorer.exe reads some of the relevant registry entries. It looks like it is during-ish or after-ish initializing the system tray.

I don't know how bad killing explorer semi-frequently is for your system. Maybe it's very bad? If you find a better way, please share. :)