简体   繁体   中英

My Batch file is only executing if it is in the right mood

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 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://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-systemparametersinfow

Also see https://docs.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); 

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.

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."
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM