Extracting icons from a file on 64-bit OS

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
JnLlnd
Posts: 487
Joined: 29 Sep 2013, 21:29
Location: Montreal, Quebec, Canada
Contact:

Extracting icons from a file on 64-bit OS

15 Aug 2016, 19:45

Hi,

I need help to make this code from Skan in an old thread to work on a 64-bit OS. I guess it does not work because it is written for 32-bit. Could you please tell me what need to be changed?

Code: Select all

$EXTRACT_ICONGROUP( A_WinDir "\regedit.exe", A_Desktop "\Regedit.ico")
return


$EXTRACT_ICONGROUP( $FILE, $TARGET, $ICONNUMBER=1 ) {
   hModule := DllCall( "LoadLibraryEx", Str, $FILE, UInt, 0, UInt, 0x2 )
   hFile := DllCall( "_lcreat", Str, $TARGET, UInt, 0 )
   sBuff := GetResource( hModule, $ICONNUMBER, (RT_GROUP_ICON := 14), nSize, hResData )
   Icons := NumGet( sBuff+0, 4, "UShort" )
   
   ; line added to check the number of icons
   MsgBox, There are %Icons% icons in this file
   
   tSize := nSize+( Icons * 2 ), VarSetCapacity( tmpBuff, tSize, 0 ), tBuff := &tmpBuff
   DllCall( "RtlMoveMemory", UInt,tBuff, UInt,sBuff, UInt,6 )
   sBuff := sBuff+06, tBuff := tBuff+06
   Loop %Icons%
      DllCall( "RtlMoveMemory", UInt,tBuff, UInt,sBuff, UInt,14 )
    , sBuff := sBuff + 14, tBuff := tBuff + 16
   DllCall( "FreeResource", UInt,hResData )
   DllCall( "_lwrite", UInt,hFile, Str,tmpBuff, UInt,tSize )
   EOF := DllCall( "_llseek", UInt,hFile, UInt,-0, UInt,2 )
   VarSetCapacity( tmpBuff, 0 )
   DataOffset := DllCall( "_llseek", UInt,hFile, UInt,18, UInt,0 )
   Loop %Icons% {
      VarSetCapacity( Data,4,0 )
      DllCall( "_lread", UInt,hFile, Str,Data, UInt,2 )
      nID := NumGet( Data, 0, "UShort" )
      DllCall( "_llseek", UInt,hFile, UInt,-2, UInt,1 )
      NumPut( EOF, Data ),   DllCall( "_lwrite", UInt,hFile, Str,Data, UInt,4 )
      DataOffset := DllCall( "_llseek", UInt,hFile, UInt,0, UInt,1 )
      sBuff := GetResource( hModule, nID, (RT_ICON:=3), nSize, hResData )
      DllCall( "_llseek", UInt,hFile, UInt,0, UInt,2 )
      DllCall( "_lwrite", UInt,hFile, UInt,sBuff, UInt,nSize )
      DllCall( "FreeResource", UInt,hResData )
      EOF := DllCall( "_llseek", UInt,hFile, UInt,-0, UInt,2 )
      DataOffset := DllCall( "_llseek", UInt,hFile, UInt,DataOffset+12, UInt,0 )
   }
   DllCall( "_lclose", UInt,hFile )
   DllCall( "FreeLibrary", UInt,hModule )
   Return, FileExist($TARGET) ? true : false
}

GetResource( hModule, rName, rType, ByRef nSize, ByRef hResData ) {
   Arg := ( rName+0 = "" ) ? "Str" : "UInt"
   hResource := DllCall( "FindResource", UInt,hModule, Arg,rName, UInt,rType )
   nSize := DllCall( "SizeofResource", UInt,hModule, UInt,hResource )
   hResData  := DllCall( "LoadResource", UInt,hModule, UInt,hResource )
   Return DllCall( "LockResource", UInt, hResData )
}
Thanks,

Jean
:thumbup: Author of freeware Quick Access Popup, the powerful Windows folders, apps and documents launcher!
:P Now working on Quick Clipboard Editor
:ugeek: The Automator's Courses on AutoHotkey
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Extracting icons from a file on 64-bit OS

15 Aug 2016, 20:09

Have you tried running it with AutoHotkey 32-bit?

Do you specifically need to save them to file or would a HICON (icon handle) be sufficient?
User avatar
JnLlnd
Posts: 487
Joined: 29 Sep 2013, 21:29
Location: Montreal, Quebec, Canada
Contact:

Re: Extracting icons from a file on 64-bit OS

15 Aug 2016, 20:29

> Have you tried running it with AutoHotkey 32-bit?

Not before you suggested. I compiled the script with the 32-bit AHK Unicode exe file. It did not work. But I am running it on 64-bit machine.

> Do you specifically need to save them to file or would a HICON (icon handle) be sufficient?

No. In fact, my initial need was to check if a file has icons in it. My intention was to strip down Skan's function to only get this info (the %Icons% value). But if you have a simpler get the number, it would be great. And it has to work on both 32/64-bit systems.
:thumbup: Author of freeware Quick Access Popup, the powerful Windows folders, apps and documents launcher!
:P Now working on Quick Clipboard Editor
:ugeek: The Automator's Courses on AutoHotkey
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Extracting icons from a file on 64-bit OS

15 Aug 2016, 22:24

Maybe LoadPicture() is all you need.


For this script, it should not matter whether the OS is 32-bit or 64-bit, only whether the script and the target file are 32-bit. (Note that for 32-bit processes, %WINDIR%\regedit.exe is redirected to the 32-bit version.)

This script would require ANSI 32-bit, not Unicode, and that's generally the case for old scripts using DllCall. In particular, _lcreat and related are extremely old APIs "provided for compatibility with 16-bit versions of Windows", and as such do not accept Unicode.

You need to pass a resource ID, not an "icon index". I don't think regedit.exe has an icon with resource ID 1, but maybe it does in some versions of Windows. This works with AutoHotkey ANSI 32-bit:

Code: Select all

$EXTRACT_ICONGROUP(A_AhkPath, A_Desktop "\test.ico", 159)
User avatar
JnLlnd
Posts: 487
Joined: 29 Sep 2013, 21:29
Location: Montreal, Quebec, Canada
Contact:

Re: Extracting icons from a file on 64-bit OS

15 Aug 2016, 22:57

OK. I see. It worked for A_AhkPath with ANSI runtime. But my app needs to be Unicode. I'll take a look at LoadPicture() after a little sleep :-) Thanks lexikos.
:thumbup: Author of freeware Quick Access Popup, the powerful Windows folders, apps and documents launcher!
:P Now working on Quick Clipboard Editor
:ugeek: The Automator's Courses on AutoHotkey

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Freddie, haomingchen1998, mmflume, scriptor2016, ShatterCoder and 90 guests