17

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.

17
RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters 1, True
3
  • 7
    This doesn't seem to work in win7 x64... anyone have something that works for that? – Jon Marnock Apr 29 '14 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 '15 at 9:28
  • Can confirm, doesn't actually refresh the desktop on Win7 x64. Tried calling both versions of RunDll just in case. – Scott Solmer Oct 12 '17 at 16:45
4
  • 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. – Nathan Strutz Sep 3 '15 at 14:01
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);
    }
}
2

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.

1
  • This solution should have more votes. It works reliably and doesn't require any scripting. – Paul Russell Aug 6 '20 at 9:24
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 '20 at 20:33
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 &

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.