0

I am trying to change my wallpaper with a relatively simple batch file:

reg add "HKEY_CURRENT_USER\control panel\desktop" /v wallpaper /t REG_SZ /d C:\Users\*censored*\Picture.jpg /f 
RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters 
exit 

This code is only working every 3rd or 4rth trial. This actually really confuses me since in my little programming history a code either worked or failed. I have never had the experience that a code has to be in the right mood to actually run ;).

My first intuition was to try the brute force way and just copy-paste this one liner a few dozen times. This did not solve the problem but quite contrary reduced the likelyhood that it actually changed my desktop wallpaper by a lot. I've also tried .png and .bmp pictures instead of .jpg. Since i am not at all educated in this type of programming, im pretty much screwed at the moment. Maybe someone of you can help me out. Thank you in advance if you can.

PS: Before anyone suggests to just change my wallpaper in the settings: I am trying to change it remotely by using alexa in order to match it with my philips hue lighting.

  • You generally have to reboot in order to change the background this way. I'm genuinely surprised that you've managed to make it work at all. – SomethingDark Nov 23 '20 at 02:50

3 Answers3

0

You are being given the function definitions which show why it probably won't work. As you are passing 0, <whatever>, null, null to a function expecting hWnd, hInst, <commandline>, WindowShowState. Also you say you are doing it remotely. Most operations like this run in a separate desktop.

Note there are restrictions on code run remotely to affect the current user..

There is only one supported way to change wallpaper.

Public Declare Unicode Function SystemParametersInfoW Lib "user32" (ByVal uAction As Integer, ByVal uParam As Integer, ByVal lpvParam As String, ByVal fuWinIni As Integer) As Integer

Public Const SPI_SETDESKWALLPAPER = 20
Public Const SPIF_SENDWININICHANGE = &H2
Public Const SPIF_UPDATEINIFILE = &H1

Ret = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, FName, SPIF_SENDWININICHANGE + SPIF_UPDATEINIFILE)

See https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfow

Also see https://learn.microsoft.com/en-au/windows-server/administration/windows-commands/rundll32 which says "Rundll32 can only call functions from a DLL explicitly written to be called by Rundll32".

This is how it must be written

 void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow); 
  • The question is about batch, not C++ or Visual Basic. – SomethingDark Nov 23 '20 at 02:52
  • It is not possible to change the wallpaper with batch. – user14122392 Nov 23 '20 at 04:42
  • You actually can use the code in the question if you run as admin, you just have to reboot after the script runs. – SomethingDark Nov 23 '20 at 04:52
  • You are being given the function definitions which show why it probably won't work. As you are passing `0, , null, null` to a function expecting `hWnd, hInst, , WindowShowState`. Also you say you are doing it remotely. Most operations like this run in a separate desktop. – user14122392 Nov 23 '20 at 05:40
  • As "Something Dark" already said, im working with a batch file at the moment. But nevertheless thanks for your time and your answer. – Ćevapčići Official Nov 23 '20 at 17:18
  • I think i have to clearify the "remote access...": Once an alexa routine is activated, a third party program that is running on my pc actually openes the file. Therefore I can not run the batch file as an administrator. @user14122392: It is working, but only occasionally. And i do not understand why. – Ćevapčići Official Nov 23 '20 at 17:23
0

How are you triggering the batch file on event? There are many scriptable ways for you to change your Windows wallpaper besides a batch file (PowerShell, node, etc.). There may be better ways to do this than a batch file.

LetMyPeopleCode
  • 1,895
  • 15
  • 20
  • This is actually quite complicated... I do have an alexa routine, that triggers an IFTTT routine, that uploads a .txt file into my onedrive. A program (AssistantCmputerControl) on my computer monitors this onedrive. Once it detects the .txt file it reads the keyword put to it, and triggers according events. Sounds unnessecarily complicated, but for commands like "Shutdown my PC" it works within 3 seconds. Nevertheless i can only trigger events that can be accessed as a file/exe with a typical "double click". Since batch worked sometimes, i figured it could be the simplest way to solve this. – Ćevapčići Official Dec 04 '20 at 15:36
0

The below is a batch / Powershell hybrid for Changing wallpapers. It was scripted for personal use and as such is based on the default %Userprofile%\Pictures directory and .jpg .bmp and .png files located within that directory tree.

<# : 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,20
:# Test for Arg 1 ; Usage output ; Offer Input or Abort
 Set "Arg1=%~1"
 If "%Arg1%" == "" (
  Call "%~f0" "/?"
  Echo/&Echo Enter path or Search Term; or press ENTER to Abort
  Set "Wallpaper="
  Set /P "Wallpaper=Enter Path or 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
 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 times should include wildcard/s: * ? and / or extension as appropriate
  Echo/ Example:
  Echo/      Search for and apply the last found .jpg file 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
 )) 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 /LIC:"%Wallpaper%" && (
  Echo/Wallpaper already applied.
  Exit /B
 )
:# Report When Multiple Matches found; Identifying Path Used.
Setlocal EnableDelayedExpansion
 If %Matches% GTR 1 (
  Echo/%Matches% Files Matched:"!Arg1!"
  Echo/File Used: "!Wallpaper!"
 )
:# 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. Do not Modify.
: end batch / begin powershell #>

Function Set-WallPaper($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."
}

T3RR0R
  • 2,747
  • 3
  • 10
  • 25