Change desktop wallpaper

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
MauricioDeAbreu
Posts: 40
Joined: 12 Dec 2021 06:45

Change desktop wallpaper

#1 Post by MauricioDeAbreu » 20 Dec 2021 16:15

Friends…
Is it possible to change the desktop wallpaper with Batch?

If possible, in what way could it be done?

Thanks in advance for the help.

ShadowThief
Expert
Posts: 1160
Joined: 06 Sep 2013 21:28
Location: Virginia, United States

Re: Change desktop wallpaper

#2 Post by ShadowThief » 20 Dec 2021 20:37

The current wallpaper is stored in the registry in HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System under the Wallpaper key.

You can

Code: Select all

reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System" /v Wallpaper /t REG_SZ /d image.jpg
and then reboot to set it. There's like a 5% chance you won't need to reboot, so just reboot.

"Is there a way to do it without needing to reboot?" No.
"But `RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters` should be able to update it without needing to reboot." Maybe. Maybe not. Try running it 5 or 10 times in a row and when that doesn't work, just reboot.

MauricioDeAbreu
Posts: 40
Joined: 12 Dec 2021 06:45

Re: Change desktop wallpaper

#3 Post by MauricioDeAbreu » 20 Dec 2021 22:04

First of all, thanks for replying.

It didn't work for me.

Thanks

T3RRY
Posts: 243
Joined: 06 May 2020 10:14

Re: Change desktop wallpaper

#4 Post by T3RRY » 21 Dec 2021 00:10

This can be done without needing to reboot via a batch / powershell hybrid.

The below is what I use personally. Note: the menu system I use in it requires windows 10 version 10586 or newer to output correctly

Code: Select all

<# : batch portion
:# The above line marks the beginning of a powershell comment block; and the Batch component of the Script. Do not modify.
::# Author: T3RRY ; Creation Date 12/02/2021 ; Version: 1.0.2
::# * Batch Powershell Hybrid * Resource: https://www.dostips.com/forum/viewtopic.php?f=3&t=5543
::# Script Purpose:
::# - Change the wallpaper from command prompt through the use of Parameter; Or by Input if no Parameter.
::# - Script Designed for use with pictures in the %Userprofile%\Pictures Directory
::#   or sub directories and should be placed in the %Userprofile%\Pictures Directory.
::#   - Hot tip: Add the %Userprofile%\Pictures Directory to your System environment Path variable.
::#     https://helpdeskgeek.com/windows-10/add-windows-path-environment-variable/

@Echo off & Mode 120,40

:# Test for Arg 1 ; Usage output ; Offer Input or Abort

 Set "Arg1=%~1"
 If "%Arg1%" == "" (
  Call "%~f0" "/?"
  Echo/
  Set "Wallpaper="
  Set /P "Wallpaper=Press ENTER to abort, or enter filepath / Search Term: "
  Setlocal EnableDelayedExpansion
  If "!Wallpaper!" == "" Exit /B
  Call "%~f0" "!Wallpaper!"
  Endlocal
  Exit /B
 )

:# Test for Unsupported Arg Count ; Notify Ignored Args; Show Help; Offer Abort

 Set ParamErr=%*
 If Not "%~2" == "" (
  Setlocal EnableDelayedExpansion
  Echo/Args:"!ParamErr:%Arg1% =!" Ignored. %~n0 only accepts 1 Arg.
  Call "%~f0" "/?"
  Endlocal
  Echo/Continue with Arg1:"%Arg1%" [Y]/[N]?
  For /F "Delims=" %%G in ('Choice /N /C:YN')Do if "%%G" == "N" Exit /B
 )
:# /Dir Switch - Display all image paths with matching extensions in tree of current Directory
 If Not "%Arg1:/Dir=%" == "%Arg1%" (
  Dir /B /S "*.jpg" "*.png" "*.bmp" | More
  Exit /B
 )

:# Usage test and output

 If Not "%Arg1:/?=%" == "%Arg1%" (
  Echo/ %~n0 Usage:
  Echo/
  Echo/ %~n0 ["wallpaper filepath" ^| "Search term"]
  Echo/      Search terms should include wildcard/s: * ? and / or extension as appropriate
  Echo/ Example:
  Echo/      Search for and select from .jpg files containing Dragon in the filename:
  Echo/     %~n0 "*Dragon*.jpg"
  Echo/
  Echo/ %~n0 [/Dir] - output list of available .jpg .png and .bmp files in the directory tree
  Echo/ %~n0 [/?] - help output
  Exit /B
 )

 Set "Wallpaper=%Arg1%"

:# Arg1 Not a valid path; Offer Addition of Wildcards to SearchTerm If not Present as Bookends
 If not exist "%Wallpaper%" If not "%Wallpaper:~0,1%" == "*" If not "%Wallpaper:~,-1%" == "*" (
  Echo/Add wildcards to "%Wallpaper%" {"*%Wallpaper%*"} [Y]/[N]?
  For /F "Delims=" %%G in ('Choice /N /C:YN')Do if "%%G" == "Y" Set "Wallpaper=*%Wallpaper%*"
 )

:# To support Search Terms run script in Top level of Directory containing Images; Find Full Path in Tree.

 PUSHD "%Userprofile%\Pictures"
 Set "Matches=0"
 (For /F "Delims=" %%G in ('Dir /B /S "%Wallpaper%"')Do (
   Set "Wallpaper=%%~fG"
   Set /A Matches+=1
   Call Set "Img[%%Matches%%]=%%~fG"
 )) 2> Nul

:# Determine if Target Wallpaper is Current Wallpaper; Notify and Exit
 reg query "HKEY_Current_User\Control Panel\desktop" -v wallpaper | %__AppDir__%findstr.exe /LC:"    wallpaper    REG_SZ    %Wallpaper%" && (
  Echo/Wallpaper already applied.
  Exit /B
 )

:# Enable environment for macro expansion, Arrays and code block variable operations
  Setlocal EnableExtensions EnableDelayedExpansion

 If NOT %Matches% GTR 1 Goto :Apply

:# Report When Multiple Matches found; Offer menu containing up to first 36 matches [ limit of menu macro ]

If %Matches% GTR 36 Set Matches=36

:# Menu Macro Author: T3RRY
:# Colored edition - Requires windows 10
:# IMPORTANT - RESERVED VARIABLES: Menu CH# CHCS Options Option Opt[i] Option.Output Cholist DIV

:# Menu macro escaped for Definition with DelayedExpansion Enabled. Ensures correct Environment:
 If not "!" == "" (
  Setlocal EnableExtensions EnableDelayedExpansion
 )

:# Test if virtual terminal codes enabled ; attempt to enable if false
 Reg Query HKCU\Console | %SystemRoot%\System32\findstr.exe /LIC:"VirtualTerminalLevel    REG_DWORD    0x1" > nul || (
   Reg Add HKCU\Console /f /v VirtualTerminalLevel /t REG_DWORD /d 1
 ) > Nul || (
  Echo(Virtual Terminal codes Required by Menu Macro not supported on your system.
  Pause
  Exit /B 1
 )

(Set \n=^^^

%= Newline var \n for multi-line macro definition - Do not modify. =%)

:# Key index list Allows maximum 36 menu options [ 0 indexed ]. Component of Menu Macro
 Set "ChoList=0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"

:# Get console width for dividing line
 for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| %SystemRoot%\System32\findstr.exe /LIC:"Columns"`) do Set /A "Console_Width=%%W"

:# Build Menu option color array [ RGB colormix ; red biased scaling darker. ]
 For /F %%E in ('Echo prompt $E^|cmd')Do Set "\E=%%E"
  Set "i=0"
 For /L %%i in (232 -4 70)Do (
  Set /A "BB=(%%i/4)+50,GG=%%i-BB,RR=GG+BB+(%%i/2)"
  Set "Color[!i!]=%\E%[38;2;!RR!;!GG!;!BB!m"
  Set /A i+=1
 )
 Set "i="

:# Define highlight color to use for a selected option
 Set "Highlight.Color=%\E%[0m%\E%[48;2;50;150;200m%\E%[31m%\E%[K"

:# Assign Flag true to enable Highlighting of selected option. Clears screen before menu is output.
 Set "Highlight=true"

:# Force console line dimensions to a size that supports highlight mode by preventing buffer scroll
 If /I "%Highlight%" == "true" (
  for /F "usebackq tokens=2* delims=: " %%W in (`mode con ^| %SystemRoot%\System32\findstr.exe /LIC:"Lines"`) do If %%W LSS 40 Mode !Console_Width!,40
 )

:# Build dividing line for menu output.
 Set "DIV=" & For /L %%i in (2 1 %Console_Width%)Do Set "DIV=!DIV!-"

:# Define dividing line Color
 Set "DIV=%\E%[33m%\E%[4m!DIV!%\E%[0m"

:# Menu macro Usage: %Menu% "quoted" "list of" "options"

     Set Menu=For %%n in (1 2)Do if %%n==2 (%\n%
%= Clear screen if highlight flag true  =%  If /I "^!Highlight^!" == "true" CLS%\n%
%= Output Dividing Line                 =%  Echo(^^!DIV^^!%\n%
%= Reset CH# index value for Opt[#]     =%  Set "CH#=0"%\n%
%= Undefine choice option key list      =%  Set "CHCS="%\n%
%= For Each in list;                    =%  For %%G in (^^!Options^^!)Do If not ^^!CH#^^! GTR 35 (%\n%
%= For Option Index value               =%   For %%i in (^^!CH#^^!)Do (%\n%
%= Build the Choice key list and Opt[#] =%    Set "CHCS=^!CHCS^!^!ChoList:~%%i,1^!"%\n%
%= array using the character at the     =%    Set "Opt[^!ChoList:~%%i,1^!]=%%~G"%\n%
%= current substring index.             =%    Set "option.output=%%~G"%\n%
%= Display ; removing # variable prefix =%    Echo(^^!Color[%%i]^^![^^!ChoList:~%%i,1^^!] ^^!Option.output:#=^^!%\E%[0m%\n%
%= Store line number of options         =%    Set "Line#^!ChoList:~%%i,1^!=%%i"%\n%
%= Increment Opt[#] Index var 'CH#'     =%    Set /A "CH#+=1"%\n%
%= Close CH# loop                       =%   )%\n%
%= Close Options loop                   =%  )%\n%
%= Output Dividing Line                 =%  Echo(^^!DIV^^!%\n%
%= Select option by character index     =%  For /F "Delims=" %%o in ('%SystemRoot%\System32\Choice.exe /N /C:^^!CHCS^^!')Do (%\n%
%= Assign return var 'OPTION' with the  =%   Set "Option=^!Opt[%%o]^!"%\n%
%= Highlight selected option with Line# =%   If /I "^!Highlight^!" == "true" (For /F "Delims=" %%X in ("^!Line#%%o^!")Do For /F "Delims=" %%Y in ('Set /A "%%X+2"')Do Echo(%\E%[%%Y;1H^^!Highlight.Color^^!{^^!Cholist:~%%X,1^^!} ^^!Opt[%%o]^^!%\E%[0m)%\n%
%= value selected from Opt[CH#] array.  =%   If /I "^!Option^!" == "Exit"   CLS ^& Exit /B 1%\n%
%= Exit type determines Errorlevel.     =%   If /I "^!Option^!" == "Previous" CLS ^& Exit /B 0%\n%
%= Return to previous script on Exit    =%  )%\n%
%= Move cursor to end of menu field     =%  If /I "^!Highlight^!" == "true" For /F "Delims=" %%Y in ('Set /A CH# + 2')Do Echo(%\E%[%%Y;1H%\n%
%= Capture Macro input - Options List   =% )Else Set Options=
========================================== :# End Definition of Menu Macro

:# Notify match count

 Echo/%Matches% Files Matched:"!Arg1!"

:# Use match count to build options list for Menu macro from IMG[ Array. Restricted to first 36 matches.
 
 Set "Menu.Options="
 For /L %%i in (1 1 %Matches%)Do Set "Menu.Options=!Menu.Options! "!Img[%%i]!""

:# Call Menu macro

 %Menu% %Menu.Options%

 Set "Wallpaper=%Option%"

 reg query "HKEY_Current_User\Control Panel\desktop" -v wallpaper | %__AppDir__%findstr.exe /LC:"    wallpaper    REG_SZ    %Wallpaper%" > nul && (
  Echo/Wallpaper already applied.
  Exit /B
 )

:Apply

:# Pipe Filepath to Powershell; Capture as Powershell Variable within Pipe; Exit on Return.
 Echo/!Wallpaper!| powershell.exe -noprofile "$Image = $input | ?{$_}; iex (${%~f0} | out-string)"
 Endlocal
 POPD
Exit /B 0

:# The below line Marks the end of a Powershell comment Block; And the End of the Batch Script. 
: end batch / begin powershell #>

<#
 Function Source: https://www.joseespitia.com/2017/09/15/set-wallpaper-powershell-function/
#>

Function Set-WallPaper {
 [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$Image
    )

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

$RefreshIni = $UpdateIniFile -bor $SendChangeEvent

$ret = [Params]::SystemParametersInfo($SPI_SETDESKWALLPAPER, 0, $Image, $RefreshIni)
}

If (Test-Path $Image) {
    Set-WallPaper -Image $Image
    write-output "Wallpaper Updated."
}else {
    write-output "Wallpaper Does not exist in the Directory Tree."
}



MauricioDeAbreu
Posts: 40
Joined: 12 Dec 2021 06:45

Re: Change desktop wallpaper

#5 Post by MauricioDeAbreu » 21 Dec 2021 12:56

First of all, thanks for replying.

Your code is perfect and works as expected

I have been slow to respond because I have tried to understand your code to adapt it to mine, but I am very far from being able to do it because of the little knowledge I have.

I wonder:
If the directory (path) of the images is always the same. And the Name of the image or the number to which the image belongs is managed with a variable (referring to the numbers that are assigned in the menu to the images).

How could your code be adapted to do what it already does without generating prompts or echoing on the screen?
Thank you in advance for the support you can give me to resolve my question.

PS I will only manage 7 images as wallpaper in the fixed directory.


T3RRY
Posts: 243
Joined: 06 May 2020 10:14

Re: Change desktop wallpaper

#7 Post by T3RRY » 22 Dec 2021 08:17

MauricioDeAbreu wrote:
21 Dec 2021 12:56
First of all, thanks for replying.

Your code is perfect and works as expected

I have been slow to respond because I have tried to understand your code to adapt it to mine, but I am very far from being able to do it because of the little knowledge I have.

I wonder:
If the directory (path) of the images is always the same. And the Name of the image or the number to which the image belongs is managed with a variable (referring to the numbers that are assigned in the menu to the images).

How could your code be adapted to do what it already does without generating prompts or echoing on the screen?
Thank you in advance for the support you can give me to resolve my question.

PS I will only manage 7 images as wallpaper in the fixed directory.
Changing the path used in the script is a simple matter, as for your question regarding modifying it so no selection prompt is shown, That depends on the behaviour you want to implement for changing wallpaper. IE:
- Pass an argument to the script in the form of a path for the image to be applied
- Pass a number as an argument to the script to apply number n of 7 predefined images
- 'Automatically' increment whatever the current image number is and apply the next in sequence
- Randomly selecting from any of the 6 images not currently assigned as the wallpaper

As you can see, there's alot to consider when approaching script design. As for "How can the above be changed to do what it does without generating prompts or output":
That would be to remove any line which produces output and modify any the methods of input to align with whatever method of handling changing from one picture to the next you want to implement.

MauricioDeAbreu
Posts: 40
Joined: 12 Dec 2021 06:45

Re: Change desktop wallpaper

#8 Post by MauricioDeAbreu » 22 Dec 2021 13:24

Friends, in addition to apologizing for the delay in responding, I want to thank the responses and contributions that you have given me.

The truth is that after a restful night, I realized how to modify the code of T3RRY.

The initial modification of the code looked like this:

Code: Select all

<# : batch portion
:# The above line marks the beginning of a powershell comment block; and the Batch component of the Script. Do not modify.
::# Author: T3RRY ; Creation Date 12/02/2021 ; Version: 1.0.2
::# * Batch Powershell Hybrid * Resource: https://www.dostips.com/forum/viewtopic.php?f=3&t=5543
::# Script Purpose:
::# - Change the wallpaper from command prompt through the use of Parameter; Or by Input if no Parameter.
::# - Script Designed for use with pictures in the %Userprofile%\Pictures Directory
::#   or sub directories and should be placed in the %Userprofile%\Pictures Directory.
::#   - Hot tip: Add the %Userprofile%\Pictures Directory to your System environment Path variable.
::#     https://helpdeskgeek.com/windows-10/add-windows-path-environment-variable/

@Echo off 

Set Wallpaper=C:\Imagenes de Alerta\Alerta de Memoria y Disco Duro.png

:# Pipe Filepath to Powershell; Capture as Powershell Variable within Pipe; Exit on Return.
 Echo/%Wallpaper%| powershell.exe -noprofile "$Image = $input | ?{$_}; iex (${%~f0} | out-string)"
 Endlocal
 POPD
Exit /B 0

:# The below line Marks the end of a Powershell comment Block; And the End of the Batch Script. 
: end batch / begin powershell #>

<#
 Function Source: https://www.joseespitia.com/2017/09/15/set-wallpaper-powershell-function/
#>

Function Set-WallPaper {
 [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [string]$Image
    )

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

$RefreshIni = $UpdateIniFile -bor $SendChangeEvent

$ret = [Params]::SystemParametersInfo($SPI_SETDESKWALLPAPER, 0, $Image, $RefreshIni)
}

If (Test-Path $Image) {
    Set-WallPaper -Image $Image
    write-output "Fondo de pantalla actualizado ."
}else {
    write-output "El fondo de pantalla no existe en el arbol de directorios ."
}
The rest was handling it with a variable and some minor adjustments.

You can mark the post as solved.

Again, thank you so much ShadowThief, T3RRY and Miskox for the help you gave me.

PD. Excuse my English, I am using a translator.

MauricioDeAbreu
Posts: 40
Joined: 12 Dec 2021 06:45

Re: Change desktop wallpaper

#9 Post by MauricioDeAbreu » 16 Jan 2022 14:18

Friends, I have a question.

Is there a way to adapt the code or do this on Windows XP y Windows Seven?

Thanks in advance for any help you can give me.

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Change desktop wallpaper

#10 Post by aGerman » 16 Jan 2022 15:54

SystemParametersInfo is available on Windows 2000 already. So I guess every Windows version that supports PowerShell should be able to run the code. However, older versions may require *.jpg or even *.bmp file formats.

Same thing in a macro code:

Code: Select all

@echo off &setlocal

REM define the "update_wallpaper" macro
::::::::::::
setlocal DisableDelayedExpansion
set update_wallpaper=for %%i in (1 2) do if %%i==2 (^
%=% for /f "tokens=*" %%j in ("^^!arg^^!") do endlocal^&powershell.exe -nop -ep Bypass -c ^"$w=Add-Type -Name WAPI -PassThru -MemberDefinition '^
%===% [DllImport(\"User32.dll\",CharSet=CharSet.Unicode)]^
%===% public static extern void SystemParametersInfoW(int uAction,int uParam,string pvParam,int fWinIni);';^
%===% $w::SystemParametersInfoW(20,0,\"%%~j\",3);^") else setlocal EnableDelayedExpansion^&set arg=
endlocal&set "update_wallpaper=%update_wallpaper%"
if !!# neq # set "update_wallpaper=%update_wallpaper:^^!=!%"
::::::::::::

REM call the "update_wallpaper" macro, passing the path of the new image file
%update_wallpaper% "C:\wallpaper\xyz.jpg"
Steffen

MauricioDeAbreu
Posts: 40
Joined: 12 Dec 2021 06:45

Re: Change desktop wallpaper

#11 Post by MauricioDeAbreu » 16 Jan 2022 17:18

Excellent aGerman

It's perfect for Windows Seven, it even works with windows 10

I am very grateful for your help.

Unfortunately, for Windows XP 64 bit, I don't find a method that changes the background efficiently.

If anyone has any tricks up their sleeve I would greatly appreciate it.

miskox
Posts: 553
Joined: 28 Jun 2010 03:46

Re: Change desktop wallpaper

#12 Post by miskox » 17 Jan 2022 02:17

My solution works on XP (at least I use it regulary on 32-bit Windows XP PRO). Can't test it on 64-bit.

Saso

MauricioDeAbreu
Posts: 40
Joined: 12 Dec 2021 06:45

Re: Change desktop wallpaper

#13 Post by MauricioDeAbreu » 17 Jan 2022 03:24

A thousand apologies, you are very right, I had forgotten that method… :oops:

I just tested it on Windows XP 64bit and it works perfectly.

Thanks again to ShadowThief, T3RRY, Miskox and aGerman for the help they have given me.

Fixed issue.

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Change desktop wallpaper

#14 Post by aGerman » 04 Feb 2022 11:18

Yesterday I found an ancient C code of mine that I wrote to change the wallpaper on XP. I was surprised it still works on Win 11 because actually the "Active Desktop" feature (where the used interface belongs to) has been replaced on Vista and isn't supported any longer.
However, based on this old code I implemented a PowerShell hybrid macro which works on Win 11. Today I updated the code to make it compatible with PowerShell 2.0. So, I guess that it is backward compatible with XP now (provided PowerShell is installed).
Unlike my previous macro, this one also gives you the opportunity to change the appearance of the wallpaper. Furthermore I did my best to make the whole code Unicode-compliant in order to support all kind of non-ASCII file names.
Don't be afraid of the length of the code. It contains quite some comments explaining what it's all about, why I wrote it like I did, and how to use it.

Steffen

NOTE: Save the code UTF-8 encoded, without Byte Order Mark!

Code: Select all

@echo off &: 𝖴𝖳𝖥⁃𝟪 𝗇𝗈 𝖡𝖮𝖬 ⵑ
:: This      ^^ comment ^^      consists of non-ASCII.
:: NOTE: The Batch script itself must first be saved UTF-8 encoded, without BOM!
:: The comment (likewise any other non-ASCII sequence in the code) helps a text
:: editor to recognize the character set. It's kind of a BOM substitute and
:: avoids that the editor considers falling back to ANSI when the script is
:: opened again.

:: No further code update is required regardless of whether delayed variable
:: expansion is enabled or disabled.
::setlocal DisableDelayedExpansion
setlocal EnableDelayedExpansion

:: Capture the current console code page, then set the active code page to UTF-8
:: for some Unicode support. UTF-8 file names do only work because PowerShell is
:: involved which performs an implicit conversion to UTF-16.
for /f "delims=" %%i in ('chcp') do for %%j in (%%i) do set "oemcp=%%~nj"
>nul chcp 65001

:: Initialize the "update_wallpaper" macro.
call :init_update_wallpaper

:: Call the "update_wallpaper" macro, passing the option and the path of the new
:: image file.
:: The code was actually tested with this weird file name containing a few
:: special patterns in Batch/PowerShell, unbalanced bracketing, and non-ASCII
:: characters that require up to 4 UTF-8 bytes. The only change from the
:: original filename is the double percent sign, as is inevitable to represent
:: a single percent sign in string literals of a Batch script.
%update_wallpaper% 4 "%%{$_}}~@())[]]+-=! &'.';,#`^ÈЯ€𐍈.jpg"
echo return value: %errorlevel%

>nul chcp %oemcp%
pause
exit /b


:init_update_wallpaper
:: -- BRIEF --
::  Change the desktop wallpaper.
:: -- SYNTAX --
::  %update_wallpaper% opt "file"
::    opt    Option specifying the appearance of the wallpaper.
::             Supported values:
::             0   Center the wallpaper image in its original size, uncovered
::                  area is filled with the background color.
::             1   Tile the wallpaper image, starting in the upper left corner
::                  of the screen.
::             2   Stretch the image to cover the full screen, changing the
::                  original aspect ratio if necessary.
::             3   (min. Win 7) Stretch the image to fit horizontally or
::                  vertically, retaining the original aspect ratio. Uncovered
::                  area is filled with the background color.
::             4   (min. Win 7) Stretch the image to cover the full screen,
::                  retaining the original aspect ratio. The image might be
::                  cropped horizontally or vertically.
::             5   (min. Win 8) Span the wallpaper across multiple monitors.
::            When in doubt, use 4 (or 2 on old Windows versions).
::    file   Name of the new image file.
:: -- RETURN --
::  0   The wallpaper has been updated. (If the file format is not supported,
::       the desktop background will default to monochrome.)
::  1   The wallpaper has not been updated. (E.g. the option is out of range or
::       the file doesn't exist.)
:: -- EXAMPLE --
::  %update_wallpaper% 4 "C:\wallpaper\example.jpg"
setlocal DisableDelayedExpansion
set update_wallpaper=for %%- in (1 2) do if %%-==2 (setlocal EnableDelayedExpansion^
%=% ^&set "p=^^!p:`=``^^!"^&set "p=^^!p:{=`{^^!"^&set "p=^^!p:}=`}^^!"^
%=% ^&for /f "tokens=1*" %%. in ("^^!p:$=`$^^!") do endlocal^&powershell.exe -nop -ep Bypass -c ^"^
%===% Add-Type '^
%=====% using System;using System.Runtime.InteropServices;using System.Threading;^
%=====% struct Opt{public int cb;public int sty;}^
%=====% [Guid(\"F490EB00-1240-11D1-9888-006097DEACF9\"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]^
%=====% interface IAD{^
%=======% [PreserveSig]int Apply(int fl);^
%=======% int _1();^
%=======% [PreserveSig]int SetWp([MarshalAs(UnmanagedType.LPWStr)]string f,int n);^
%=======% int _2();^
%=======% [PreserveSig]int SetOpt(ref Opt o,int n);^
%=====% }^
%=====% public class Wp{^
%=======% static string f;static Opt o;static bool r;^
%=======% static void Thd(){^
%=========% IAD d=(IAD)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(\"75048700-EF1F-11D0-9888-006097DEACF9\")));^
%=========% r=d.SetOpt(ref o,0)==0^^^^^^^&^^^^^^^&d.SetWp(f,0)==0^^^^^^^&^^^^^^^&d.Apply(23)==0;^
%=======% }^
%=======% public static bool Set(string file,int style){^
%=========% f=file;o.cb=8;o.sty=style;^
%=========% Thread t=new Thread(Thd);^
%=========% t.SetApartmentState(ApartmentState.STA);^
%=========% t.Start();^
%=========% t.Join();^
%=========% return r;^
%=======% }^
%=====% }^
%===% ';^
%===% [IO.Directory]::SetCurrentDirectory($pwd);$f=[IO.Path]::GetFullPath(\"%%~/\");^
%===% exit -not ((0..5 -contains %%~.) -and [IO.File]::Exists($f) -and [Wp]::Set($f,%%~.))^"^
%=% ^&endlocal) else setlocal DisableDelayedExpansion^&set p=
endlocal&set "update_wallpaper=%update_wallpaper%"
if !!# neq # set "update_wallpaper=%update_wallpaper:^^!=!%"
exit /b

:: A few words about the macro code:
:: PowerShell requires that characters `, {, }, and $ are escaped with a
:: preceding backtick in a string literal. This needs to be done in the Batch
:: part of the macro. The PowerShell part wraps the IActiveDesktop COM interface
:: in C# code and calls its SetWallpaper, SetWallpaperOptions, and ApplyChanges
:: methods (aliased as IAD, SetWp, SetOpt, and Apply to shorten the macro). The
:: IActiveDesktop interface must be used from within an implemented thread
:: function running in a single-threaded apartment.

MauricioDeAbreu
Posts: 40
Joined: 12 Dec 2021 06:45

Re: Change desktop wallpaper

#15 Post by MauricioDeAbreu » 08 Feb 2022 18:02

First of all, I apologize for the delay in responding, it has been impossible for me to do so until today.

On the other hand, thanks for the answer. It is always nice to try new alternatives and learn new things.

There is a detail, which I haven't been able to cover, and you have touched on it in your answer. It is about PowerShell for Windows XP, I have certainly found an installation package, but only for 32Bit, for Windows XP 64Bits which is the one I am using, I have not found any installation package.

If you know where I can find it that would be great.

I'm going to review the code and do some tests...

Thank you as always for all the help you have given me.

Post Reply