#include-once
#include <WinAPIReg.au3>
#include <WinAPISys.au3>
#include <WinAPIShPath.au3>
#include <WinAPIShellEx.au3>
; #INDEX# =======================================================================================================================
; Title .........: _FileGetIcon
; AutoIt Version : 3.3.14.5
; Language ......: English
; Description ...: Function for getting file icons.
; Author(s) .....: Rob Saunders (therks)
; ===============================================================================================================================
; #FUNCTION# ====================================================================================================================
; Name...........: _FileGetIcon
; Description ...: Get icon location for a file path/type.
; Syntax.........: _FileGetIcon($sFilePath)
; Parameters ....: $sFilePath - Path to file, folder, URL, etc.
; Return values .: Returns 2 element array: [0] = Icon file path, [1] = icon index/ordinal.
; Failure: Sets @error:
; |1 - Path is drive root but cannot determine drive type
; |2 - Path is shortcut file but unable to read it
; |3 - The extension is not registered
; |4 - The filetype is not registered or has no DefaultIcon set
; |5 - Icon file does not exist and cannot be found
; |6 - Icon is invalid and cannot be loaded
; Author ........: Rob Saunders (rob at therks dot com)
; Modified.......: Rewrite to use more reliable WinAPI functions
; ===============================================================================================================================
Func _FileGetIcon($sFilePath, $sDefaultIcon = '', $sDefaultIndex = '')
Local $t_SHFILEINFO = DllStructCreate($tagSHFILEINFO) ; ptr hIcon;int iIcon;dword Attributes;wchar DisplayName[260];wchar TypeName[80]
_WinAPI_ShellGetFileInfo($sFilePath, BitOR($SHGFI_ICONLOCATION, $SHGFI_TYPENAME), $FILE_ATTRIBUTE_NORMAL, $t_SHFILEINFO) ; #include <WinAPIShellEx.au3>
Local $aReturnIcon = [ DllStructGetData($t_SHFILEINFO, 'DisplayName'), DllStructGetData($t_SHFILEINFO, 'iIcon') ] ; Initialize $aReturnIcon
If Not $aReturnIcon[0] Then
; If no icon from ShellGetFileInfo, try AssocQueryString
Local $sExt, $sIconData
Local $aCheckProtocol = StringRegExp($sFilePath, '^(.+?)://', 1) ; check for protocol style path (ie: http://, file://, ftp://, etc)
If Not @error Then
If $aCheckProtocol[0] = 'file' Then
; If path is a file URL, convert to normal file path and pass to function
Return _FileGetIcon(_WinAPI_PathCreateFromUrl($sFilePath)) ; #include <WinAPIShPath.au3>
Else
; Get registry data for the protocol
$sIconData = _WinAPI_AssocQueryString($aCheckProtocol[0], $ASSOCSTR_DEFAULTICON) ; #include <WinAPIReg.au3>
$aReturnIcon = _WinAPI_PathParseIconLocation($sIconData) ; #include <WinAPIShPath.au3>
EndIf
Else
$sExt = _WinAPI_PathFindExtension($sFilePath) ; #include <WinAPIShPath.au3>
; Special case extension processing
Switch $sExt
Case '.lnk'
; Analyze shortcut files to get the icon
Local $aShortcut = FileGetShortcut($sFilePath)
If Not @error Then
If $aShortcut[4] Then
; If the shortcut has a custom icon
Local $aReturnIcon = [ $aShortcut[4], $aShortcut[5] ]
Else
; If no custom icon, pass shortcut target to function
Return _FileGetIcon($aShortcut[0])
EndIf
EndIf
Case '.url'
; Analyze .URL file data for custom icons
$aReturnIcon[0] = IniRead($sFilePath, 'InternetShortcut', 'IconFile', '')
$aReturnIcon[1] = IniRead($sFilePath, 'InternetShortcut', 'IconIndex', '')
Case '.scr', '.exe'
; .exe is good for returning %1, but .scr seems to return blank
$aReturnIcon[0] = $sFilePath
EndSwitch
If Not $aReturnIcon[0] Then
; We put this outside the switch in case one of the special case methods returned an empty icon
; We can still maybe get an icon by filetype
$sIconData = _WinAPI_AssocQueryString($sExt, $ASSOCSTR_DEFAULTICON) ; #include <WinAPIReg.au3>
$aReturnIcon = _WinAPI_PathParseIconLocation($sIconData) ; #include <WinAPIShPath.au3>
EndIf
EndIf
EndIf
If $aReturnIcon[0] = '%1' Then
$aReturnIcon[0] = $sFilePath
Else
If $aReturnIcon[1] < 0 Then
$aReturnIcon[1] = -$aReturnIcon[1]
Else
$aReturnIcon[1] = -($aReturnIcon[1]+1)
EndIf
EndIf
If UBound($aReturnIcon) <> 2 Or Not $aReturnIcon[0] Then
Local $aReturnIcon = [ $sDefaultIcon, $sDefaultIndex ]
Return SetError(1, 0, $aReturnIcon)
Else
$aReturnIcon[0] = _WinAPI_PathFindOnPath(FileGetLongName(_WinAPI_ExpandEnvironmentStrings($aReturnIcon[0]))) ; #include <WinAPIShPath.au3> / #include <WinAPISys.au3>
Return $aReturnIcon
EndIf
EndFunc