Change and refresh icons programmatically (without rebooting)

断了今生、忘了曾经 提交于 2019-12-05 01:11:51

问题


When I'm replacing icons manually (i.e. NOT from the Folder Options window in explorer), the icon(s) aren't being updated. For example, if I execute this batch code:

REG ADD HKCR\testfile\DefaultIcon /ve /d "C:\test.ico,0" /f

the icon(s) show like they should in the list in Folder Options, but the icons aren't updated on the desktop or in explorer.

The icons are updated if I just hit the "change icon" button for any file type and exit the Folder Options window. But this can't be done via batch or VBS as far as I know.

Restarting explorer.exe DOES work, but if I do that, the application tabs in the task bar become buggy for some reason (e.g.: when an application is maximized, I can't just left click the tab in the task bar to minimize it anymore - I have to actually right click it and hit minimize...). Not to mention, if I do it that way, all open explorer windows will close down, and that's a little bothersome.

I also have a copy of TuneUp Utilities, which has an option for reloading the icon cache, and this does work like intended. But once again, I can't access this tool via batch or VBS. And it doesn't restart explorer.exe or remove any files (like some solutions do). I'm positive of this since I don't have iconcache.db files anywhere on my OS drive.

I also tried adding the registry entries via VBS instead, but that didn't help.

Any batch or VBScript solutions are welcome!


回答1:


By associating files, the system refreshes the icons, so my simple solution was just this:

ASSOC .anyextension=anytype
ASSOC .anyextension=

Second row disassociates the extension.




回答2:


This page has a VB program that rebuilds the cache (look at frmRebuiltIconCache.frm for the actual code)

What it does is to examine the value of HKCU\Control Panel\Desktop\WindowMetrics\Shell Icon Size, subtract 1 from it, forces a timeout via SendMessageTimeout, then resets the value, and repeats the timeout

due to the fact you cannot call a DLL from vbs (without an external program), this may not give you what you need. I have pared down the program to this:

'SendMessageTimeout values
Const HWND_BROADCAST = &HFFFF
Const WM_SETTINGCHANGE = &H1A
Const SPI_SETNONCLIENTMETRICS = &H2A
Const SMTO_ABORTIFHUNG = &H2

'Private Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" _
'  (ByVal hwnd As Long, ByVal msg As Long, _
'  ByVal wParam As Long, ByVal lParam As Long, _
'  ByVal fuFlags As Long, ByVal uTimeout As Long, _
'  lpdwResult As Long) As Long

Dim icon_size
Dim new_icon_size
Dim result
Dim SysVarReg
Set SysVarReg = WScript.CreateObject("WScript.Shell")
    ' Get the current icon size.
icon_size = SysVarReg.RegRead ("HKCU\Control Panel\Desktop\WindowMetrics\Shell Icon Size")
    ' Increase the value by 1.
new_icon_size = CInt(icon_size) + 1
SysVarReg.RegWrite "HKCU\Control Panel\Desktop\WindowMetrics\Shell Icon Size", new_icon_size
    ' Send HWND_BROADCAST to refresh the icons.
SendMessageTimeout HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 10000, result
    ' Restore the original value.
SysVarReg.RegWrite "HKCU\Control Panel\Desktop\WindowMetrics\Shell Icon Size", icon_size
    ' Send HWND_BROADCAST to refresh the icons again.
SendMessageTimeout HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 10000, result

but without something to wrap the DLL call in, you will be unable to do this via vbs




回答3:


' It work in XP.

' The following is "VBA" Module.

' ---------------------------------------------------------

'SendMessageTimeout values
Const HWND_BROADCAST = &HFFFF
Const WM_SETTINGCHANGE = &H1A
Const SPI_SETNONCLIENTMETRICS = &H2A
Const SMTO_ABORTIFHUNG = &H2

Private Declare Function SendMessageTimeout Lib "user32" Alias "SendMessageTimeoutA" _
  (ByVal hwnd As Long, ByVal msg As Long, _
  ByVal wParam As Long, ByVal lParam As Long, _
  ByVal fuFlags As Long, ByVal uTimeout As Long, _
  lpdwResult As Long) As Long


Sub Rebuild_Icon_cache()

Dim icon_size
Dim new_icon_size
Dim result
Dim SysVarReg

Set SysVarReg = CreateObject("WScript.Shell")

' Get the current icon size.
icon_size = SysVarReg.RegRead("HKCU\Control Panel\Desktop\WindowMetrics\Shell Icon Size")

' Increase the value by 1.
new_icon_size = CInt(icon_size) + 1
SysVarReg.RegWrite "HKCU\Control Panel\Desktop\WindowMetrics\Shell Icon Size", new_icon_size

' Send HWND_BROADCAST to refresh the icons.
SendMessageTimeout HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 10000, result

' Restore the original value.
SysVarReg.RegWrite "HKCU\Control Panel\Desktop\WindowMetrics\Shell Icon Size", icon_size

' Send HWND_BROADCAST to refresh the icons again.
SendMessageTimeout HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0, SMTO_ABORTIFHUNG, 10000, result

End Sub


来源:https://stackoverflow.com/questions/13263577/change-and-refresh-icons-programmatically-without-rebooting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!