Jump to content
Sign in to follow this  
engine

Rebuild Shell Icon Cache

Recommended Posts

engine

I use AutoIt to write file associations to the registry. After that I need to rebuild the shell icon cache so the new icons get updated. I can´t find an AutoIt built in function and don't know how to make my own.

Here is my script for 7-Zip. I use it on my unattended windows installation.

#NoTrayIcon

$g_szVersion = "7-Zip AutoIt v3 Script 1.0"
If WinExists($g_szVersion) Then Exit; It's already running
AutoItWinSetTitle($g_szVersion)

$7zPath = RegRead("HKLM\SOFTWARE\7-Zip", "Path")

Dim $EXT[2][25] = [["7z", "arj", "bz2", "bzip2", "cab", "cpio", "deb", "gz", "gzip", "iso", "lha", "lzh", "rar", "rpm", "split", "swm", "tar", "taz", "tbz", "tbz2", "tgz", "tpz", "wim", "z", "zip"], [0, 4, 2, 2, 7, 12, 11, 14, 14, 8, 6, 6, 3, 10, 9, 15, 13, 5, 2, 2, 14, 14, 15, 5, 1]]

For $i = 0 To 24
    RegWrite("HKCR\." & $EXT[0][$i], "", "REG_SZ", "7-Zip." & $EXT[0][$i])
    RegWrite("HKCR\7-Zip." & $EXT[0][$i], "", "REG_SZ", $EXT[0][$i] & " Archive")
    RegWrite("HKCR\7-Zip." & $EXT[0][$i] & "\DefaultIcon", "", "REG_SZ", $7zPath & "7z.dll," & $EXT[1][$i])
    RegWrite("HKCR\7-Zip." & $EXT[0][$i] & "\shell\open\command", "", "REG_SZ", """" & $7zPath & "7zFM.exe" & """" & " ""%1""")
Next

Exit

My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
ProgAndy

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites
GEOSoft

For the rebuilding of the icon cache

For XP you can use FileDelete(@UserProfileDir & "\Local Settings\Application Data\IconCache.db")

For Win9x systems it's FileDelete(@WindowsDir & "\shelliconcache")

The files will be re-created.


George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites
engine

You should use _Singleton() to check if it's already running, WinExists() can fail/be tricked very easily

So it would be like this?

#Include <Misc.au3>
$g_szVersion = "7-Zip AutoIt v3 Script 1.0"
_Singleton($g_szVersion, 0); It's already running
AutoItWinSetTitle($g_szVersion)

My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
engine

For the rebuilding of the icon cache

For XP you can use FileDelete(@UserProfileDir & "\Local Settings\Application Data\IconCache.db")

For Win9x systems it's FileDelete(@WindowsDir & "\shelliconcache")

The files will be re-created.

You still need to reboot or kill the "explorer.exe" process.


My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
AdmiralAlkex

So it would be like this?

#Include <Misc.au3>
$g_szVersion = "7-Zip AutoIt v3 Script 1.0"
_Singleton($g_szVersion, 0); It's already running
AutoItWinSetTitle($g_szVersion)
Looks right :)

Share this post


Link to post
Share on other sites
engine

Looks right :)

Thanks for the reply.

Actually I found I don't need this line:

AutoItWinSetTitle($g_szVersion)

So it would be more like this:

#Include <Misc.au3>
_Singleton("7-Zip AutoIt v3 Script 1.0", 0); It's already running

Simpler!

Regards.


My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
engine

Try This:

$aRet = DllCall("shell32.dll","int",660,"int",1) ;660 = FileIconInit
MsgBox(0,0,$aRet[0])

Took from here: http://msdn.microsoft.com/en-us/library/bb776418(VS.85).aspx

Thanks.

It isn't working here!

Regards.


My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
engine

Hi.

Based on this -> http://vbnet.mvps.org/index.html?code/reg/screenrefresh.htm

and this -> http://msdn.microsoft.com/en-us/library/ms644952(VS.85).aspx

I was able to get to this:

Func _RefreshShellIconCache()
    Local Const $sKeyName = "HKCU\Control Panel\Desktop\WindowMetrics"
    Local Const $sValue = "Shell Icon Size"
    $sDataRet = RegRead($sKeyName, $sValue)
    If @error Then Return SetError(1)
    RegWrite($sKeyName, $sValue, "REG_SZ", $sDataRet + 1)
    If @error Then Return SetError(1)
    $aBC = _BroadcastChange()
    RegWrite($sKeyName, $sValue, "REG_SZ", $sDataRet)
    $bBC = _BroadcastChange()
    If $aBC = 0 Or $bBC = 0 Then Return SetError(1)
EndFunc

Func _BroadcastChange()
    $BCResult = DllCall("user32.dll", "lresult", "SendMessageTimeout", "hwnd", 65535, "uint", 26, "wparam", 42, "lparam", 0, _
        "uint", 2, "uint", 10000, "dword*", "success")
    If @error Then Return 0
    Return $BCResult[0]
EndFunc

It does what it is meant for. The problem is that all icons on the desktop are aligned on the left.

Edited by engine

My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
GEOSoft

Hi.

Based on this -> http://vbnet.mvps.org/index.html?code/reg/screenrefresh.htm

and this -> http://msdn.microsoft.com/en-us/library/ms644952(VS.85).aspx

I was able to get to this:

Func _RefreshShellIconCache()
    Local Const $sKeyName = "HKCU\Control Panel\Desktop\WindowMetrics"
    Local Const $sValue = "Shell Icon Size"
    $sDataRet = RegRead($sKeyName, $sValue)
    If @error Then Return SetError(1)
    RegWrite($sKeyName, $sValue, "REG_SZ", $sDataRet + 1)
    If @error Then Return SetError(1)
    $aBC = _BroadcastChange()
    RegWrite($sKeyName, $sValue, "REG_SZ", $sDataRet)
    $bBC = _BroadcastChange()
    If $aBC = 0 Or $bBC = 0 Then Return SetError(1)
EndFunc

Func _BroadcastChange()
    $BCResult = DllCall("user32.dll", "lparam", "SendMessageTimeout", "hwnd", 65535, "uint", 26, "wparam", 42, "lparam", 0, _
        "uint", 2, "uint", 10000, "lparam", "success")
    If @error Then Return 0
    Return $BCResult[0]
EndFunc

It does what it is meant for. The problem is that all icons on the desktop are aligned on the left.

No matter how you rebuild the cache it will set the icons to the default which is Auto-arrange, snap to grid starting from the top left. I usually just use TweakUI and it does the same.

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites
engine

Well. This:

BOOL FileIconInit(

BOOL fRestoreCache

);

(...)

Minimum DLL Version shell32.dll

Custom Implementation No

Import library None

Minimum operating systems Windows NT 4.0, Windows XP

should to the trick. My problem is translating it to AutoIt language.


My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
engine

No matter how you rebuild the cache it will set the icons to the default which is Auto-arrange, snap to grid starting from the top left. I usually just use TweakUI and it does the same.

My problem is that I don't want to rebuild the icon cache. I want to immediately see the new icons when I assign a file extension to an application.

My function is rebuilding it. So I changed it's name:

Func _RebuildShellIconCache()
    Local Const $sKeyName = "HKCU\Control Panel\Desktop\WindowMetrics"
    Local Const $sValue = "Shell Icon Size"
    $sDataRet = RegRead($sKeyName, $sValue)
    If @error Then Return SetError(1)
    RegWrite($sKeyName, $sValue, "REG_SZ", $sDataRet + 1)
    If @error Then Return SetError(1)
    $aBC = _BroadcastChange()
    RegWrite($sKeyName, $sValue, "REG_SZ", $sDataRet)
    $bBC = _BroadcastChange()
    If $aBC = 0 Or $bBC = 0 Then Return SetError(1)
EndFunc

Func _BroadcastChange()
    $BCResult = DllCall("user32.dll", "lresult", "SendMessageTimeout", "hwnd", 65535, "uint", 26, "wparam", 42, "lparam", 0, _
        "uint", 2, "uint", 10000, "dword*", "success")
    If @error Then Return 0
    Return $BCResult[0]
EndFunc
Edited by engine

My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
engine

This is an easier to read version, considering the sources. If anyone is interested.

Func _RebuildShellIconCache()
    Local Const $sKeyName = "HKCU\Control Panel\Desktop\WindowMetrics"
    Local Const $sValue = "Shell Icon Size"
    
    $sDataRet = RegRead($sKeyName, $sValue)
    If @error Then Return SetError(1)
    
    RegWrite($sKeyName, $sValue, "REG_SZ", $sDataRet + 1)
    If @error Then Return SetError(1)
    
    $bcA = _BroadcastChange()
    
    RegWrite($sKeyName, $sValue, "REG_SZ", $sDataRet)
    
    $bcB = _BroadcastChange()
    
    If $bcA = 0 Or $bcB = 0 Then Return SetError(1)
    
    Return
EndFunc ;==> _RebuildShellIconCache()

Func _BroadcastChange()
    Local Const $HWND_BROADCAST = 0xffff
    Local Const $WM_SETTINGCHANGE = 0x1a
    Local Const $SPI_SETNONCLIENTMETRICS = 0x2a
    Local Const $SMTO_ABORTIFHUNG = 0x2
    
    $bcResult = DllCall("user32.dll", "lresult", "SendMessageTimeout", _
        "hwnd", $HWND_BROADCAST, _
            "uint", $WM_SETTINGCHANGE, _
                "wparam", $SPI_SETNONCLIENTMETRICS, _
                    "lparam", 0, _
                        "uint", $SMTO_ABORTIFHUNG, _
                            "uint", 10000, _
                                "dword*", "success")
    If @error Then Return 0
    
    Return $bcResult[0]
EndFunc ;==> _BroadcastChange()

My contributions:Local account UDF Registry UDFs DriverSigning UDF Windows Services UDF [url="http://www.autoitscript.com/forum/index.php?showtopic=81880"][/url]

Share this post


Link to post
Share on other sites
exodius

This is great. To take care of the fact that it messes up the Desktop icons I borrowed this from MrCreatoR's Desktop Icon Restorator (check it out if you haven't yet):

#include <GuiListView.au3>
FileDelete ("A.ini") ; Just to make sure the file doesn't already exist, A.ini could be anything/anywhere
_Write_DSI_Session ("A.ini")
MsgBox (0, "", "A MsgBox just to create a delay, I use the _RebuildShellIconCache function here")
_RestoreSession("A.ini")
FileDelete ("A.ini")

Func _Write_DSI_Session($sFile)
    ;Check For Ability to Write
    Local $OpFile = FileOpen($sFile, 9)
    If $OpFile = -1 Then Return SetError(1)
    FileClose($OpFile)

    ;Drop all previous icon positions
    IniDelete($sFile, "Icons")

    Local $sIconText, $aPos
    ;Get a handle on the desktop, which is actually a listview control.
    Local $hWnd_LV = ControlGetHandle("[CLASS:Progman]", "", "SysListView321")

    ;Walk the listview items, saving their positions to the DSI file.
    For $nIdx = 0 To _GUICtrlListView_GetItemCount($hWnd_LV) - 1
        $sIconText = _GUICtrlListView_GetItemText($hWnd_LV, $nIdx)
        $aPos = _GUICtrlListView_GetItemPosition($hWnd_LV, $nIdx)
        IniWrite($sFile, "Icons", $sIconText, $aPos[0] & ";" & $aPos[1])
    Next
EndFunc

Func _RestoreSession($Dsi_File)
    ;Get a handle on the desktop, which is actually a listview control.
    $hWnd_LV = ControlGetHandle("[CLASS:Progman]", "", "SysListView321")

    $ItemsArr = IniReadSection($Dsi_File, "Icons")
    For $iCount = 1 To 3
        ;Walk the listview items, applying their positions from the INI file.
        For $nIdx = 0 To $ItemsArr[0][0]
            $sIconText = _GUICtrlListView_GetItemText($hWnd_LV, $nIdx)
            $aPos = StringSplit(IniRead($Dsi_File, "Icons", $sIconText, ""), ";")
            If IsArray($aPos) And $aPos[0] = 2 Then _GUICtrlListView_SetItemPosition($hWnd_LV, $nIdx, $aPos[1], $aPos[2])
        Next
    Next
    ControlSend("[CLASS:Progman]", "", "SysListView321", "{F5}")
EndFunc
Edited by exodius

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×