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.
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.
RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters 1, True
RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters 1, True
seems to work on my machine (note the missing comma behind UpdatePerUserSystemParameters)
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.
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);
}
}
# 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
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)
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 &