18

If I manually change the background image in the registry, how can I force it to refresh without logging off?

I know that bginfo does it, but I would like to keep things simple and not use any software.

7 Answers 7

20
RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters 1, True
5
  • 7
    This doesn't seem to work in win7 x64... anyone have something that works for that? Apr 29, 2014 at 1:50
  • 3
    Using it as RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters 1, True seems to work on my machine (note the missing comma behind UpdatePerUserSystemParameters)
    – Nebula
    Aug 11, 2015 at 9:28
  • Can confirm, doesn't actually refresh the desktop on Win7 x64. Tried calling both versions of RunDll just in case. Oct 12, 2017 at 16:45
  • The RUNDLL32 method sometimes work, sometimes not :-( Feb 21, 2023 at 3:16
  • Thank you so much!
    – Mdev
    Dec 9, 2023 at 7:08
5
  • Open Task manager
  • Kill explorer.exe
  • If the shell doesn't immediately restart
  • From the menu select File > New Task
  • Type "explorer.exe" and hit enter.
1
  • Good thought, but that simply doesn't solve it. Sep 3, 2015 at 14:01
4

Change the screen resolution, then choose the revert option. Your resolution will remain the same and the background will have changed.

Alternatively, disconnect and reconnect the display cable.

2
  • This solution should have more votes. It works reliably and doesn't require any scripting. Aug 6, 2020 at 9:24
  • This is the best solution indeed. No scripting, just some mouse clicks and works for all windows versions.
    – taiyo
    Feb 7 at 15:19
2

I was trying to do something similar - update a registry setting for the start menu and then immediately have the start menu reflect the changes.

The solution from this MSDN question worked for me perfectly.

You could try broadcasting a WM_SETTINGCHANGE message. For example:

class Program
{
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SendMessageTimeout(IntPtr hWnd, int Msg, IntPtr wParam, string lParam, uint fuFlags, uint uTimeout, IntPtr lpdwResult);

    private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff);
    private const int WM_SETTINGCHANGE = 0x1a;
    private const int SMTO_ABORTIFHUNG = 0x0002;

    static void Main(string[] args)
    {
        SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero);
    }
}
1
# first in powershell, second both. cmd.exe + powershell.exe

# Refresh Desktop Ability
$definition = @'
    [System.Runtime.InteropServices.DllImport("Shell32.dll")] 
    private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);
    public static void Refresh() {
        SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);    
    }
'@
Add-Type -MemberDefinition $definition -Namespace WinAPI -Name Explorer

# Set Safe within deleted days and get physical drive letters
$ignoreDeletedWithinDays = 2
$drives = (gwmi -Class Win32_LogicalDisk | ? {$_.drivetype -eq 3}).deviceid

# Process discovered drives
$drives | % {$drive = $_
    gci -Path ($drive+'\$Recycle.Bin\*\$I*') -Recurse -Force | ? {($_.LastWriteTime -lt [datetime]::Now.AddDays(-$ignoreDeletedWithinDays)) -and ($_.name -like "`$*.*")} | % {

        # Just a few calcs
        $infoFile         = $_
        $originalFile     = gi ($drive+"\`$Recycle.Bin\*\`$R$($infoFile.Name.Substring(2))") -Force
        $originalLocation = [regex]::match([string](gc $infoFile.FullName -Force -Encoding Unicode),($drive+'[^<>:"/|?*]+\.[\w\-_\+]+')).Value
        $deletedDate      = $infoFile.LastWriteTime
        $sid              = $infoFile.FullName.split('\') | ? {$_ -like "S-1-5*"}
        $user             = try{(gpv "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\$($sid)" -Name ProfileImagePath).replace("$(gpv 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion\ProfileList' -Name ProfilesDirectory)\",'')}catch{$Sid}

        #' Various info
        $originalLocation
        $deletedDate
        $user
        $sid
        $infoFile.Fullname
        ((gi $infoFile -force).length / 1mb).ToString('0.00MB')
        $originalFile.fullname
        ((gi $originalFile -force).length / 1mb).ToString('0.00MB')
        ""

        # Blow it all Away
        #ri $InfoFile -Recurse -Force -Confirm:$false -WhatIf
        #ri $OriginalFile -Recurse -Force -Confirm:$false- WhatIf
        # remove comment before two lines above and the '-WhatIf' statement to delete files
    }
}

# Refresh desktop icons
[WinAPI.Explorer]::Refresh()

or 

ie4uinit.exe -ClearIconCache

end scripting enjoy.
#end
1
  • 1
    This look nice, but why all the drive stuff in there?
    – not2qubit
    Jan 9, 2020 at 20:33
1

Apparently, "RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters 1, True" leads to inconsistent results (at least on my PC). I found the following PowerShell script, that always works on my PC: https://c-nergy.be/blog/?p=15291, option 2:

#-------------------------------------------------------------------#
# ScriptName : SetWall.ps1                                          #
# Description : Force a Desktop wallpaper Refresh                   #
# Credits  : Unknown (if you know original creator, let us know)    #
#                                                                   #
# Date : 01 July 2020                                               #
#-------------------------------------------------------------------#

#Modify Path to the picture accordingly to reflect your infrastructure
$imgPath="\\Domain.lab\netlogon\Wallpaper.png"
$code = @' 
using System.Runtime.InteropServices; 
namespace Win32{ 
    
     public class Wallpaper{ 
        [DllImport("user32.dll", CharSet=CharSet.Auto)] 
         static extern int SystemParametersInfo (int uAction , int uParam , string lpvParam , int fuWinIni) ; 
         
         public static void SetWallpaper(string thePath){ 
            SystemParametersInfo(20,0,thePath,3); 
         }
    }
 } 
'@

add-type $code 

#Apply the Change on the system 
[Win32.Wallpaper]::SetWallpaper($imgPath)
0

The line from the accepted answer worked for me very sporadically. I ended up writing a while loop to call the code silently in the background 25 times. Hope this helps.

Code from the accepted answer:

RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters 1, True

Code from the top of my bash script:

desktop () {

i=0

# Tell the desktop to refresh 25 times.
while [ $i -le 25 ]
do
  echo "RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters, 1 True"| "C:/Windows/System32/WindowsPowerShell/v1.0/powershell"
  ((i++))
done

}


# This runs the function silently as a background process
desktop &>/dev/null &

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .