Sign in to follow this  
Followers 0
maroesjk

Save the first icon of an exe

18 posts in this topic

I created some software that automatically compiles an AutoItScript (lets say: launcher.exe) to launch some specific software (lets say: software.exe) on my USB-drive. What I would like to do is to give laucher.exe the same icon as the first one in software.exe. But as Aut2Exe only works with single *.ico's I need to extract the icon.

For now, I'm doing that by hand (external program), but I guess it should be possible to (automatically):

- Extract the first icon of an executable with AutoIt

- And save it as an *.ico-file

without the help of external programs

I guess it requires calling API's, but whatever I do, I can't seem to fix/script it! Any help would be appreciated.

Share this post


Link to post
Share on other sites



i saw a few icon extractor programs in example scripts..

Share this post


Link to post
Share on other sites

i saw a few icon extractor programs in example scripts..

I saw those too, but those extractor programs normally extract all icons, and I only need the first one. Next, I think it should be possible without the help of external programs. The only question is: HOW :)

Share this post


Link to post
Share on other sites

#include <GDIPlus.au3>
; #include <IconChooser.au3> ;http://www.autoit.de/index.php?page=Thread&postID=31304#post31304

#include<WindowsConstants.au3>
#include<ButtonConstants.au3>
#include<EditConstants.au3>
#include<GUIConstantsEx.au3>
#include<StaticConstants.au3>



$Icon = _ChooseIcon()
If $Icon[0] = "" Then Exit MsgBox(0, 'Exit', "No Icon chosen")
$Ret = DllCall("shell32","long","ExtractAssociatedIcon","int",0,"str",$Icon[0],"int*",(-1*$Icon[1])-1)
$hIcon = $Ret[0]
_GDIPlus_Startup()
        $pBitmap = DllCall($ghGDIPDll,"int","GdipCreateBitmapFromHICON", "ptr",$hIcon, "int*",0)
        $pBitmap = $pBitmap[2]
_GDIPlus_ImageSaveToFile($pBitmap, @ScriptDir & "\Test.jpg")
_GDIPlus_ImageDispose($pBitmap)
_GDIPlus_Shutdown()
_WinAPI_DestroyIcon($Ret[0])
MsgBox(0, "#" & $Icon[1], @error)

exit; 

#cs
;;; icon chooseer 

#include<WindowsConstants.au3>
#include<ButtonConstants.au3>
#include<EditConstants.au3>
#include<GUIConstantsEx.au3>
#include<StaticConstants.au3>
#ce

;===============================================================================
;
; Description:      Show all icons in the given file and choose one.
; Requirement(s):   Autoit v3.2.8.1+
; Author(s):        Prog@ndy (some Functions and Gui-Style by YDY (Lazycat) (in enumicons_v2))
; Version:          1.0
; Date:             02.11.2007
;
; How to Call: $ret = _ChooseIcon( [Optional: Filename] )
; Return Values: Array:
;                        [0] = FileName
;                        [1] = Icon Number
;
;===============================================================================
#cs Example
$ret = _ChooseIcon()
MsgBox(0,"Icon","Pfad: " & $ret[0] & @CRLF & "icon-Nr.: " & $ret[1])
#ce


Func _ChooseIcon($fFileName = "")

    Local $_CI_IconCount, $_CI_FileName, $_CI_SelectedIconName, $_CI_IconRadios[30], $_CI_Labels[30],$_CI_NewFile
    Local $_CI_oldEventMode = Opt("GuiOnEventMode",0)
    Local $_CI_StartIndex = 1
    Local $arTemp[2]
    If FileExists($fFileName) Then 
        Local $_CI_FileName = $fFileName 
    Else 
        Local $_CI_FileName = @SystemDir & "\shell32.dll"
    EndIf

    Local $_CI_hGui=GUICreate("Choose Icon:", 385, 450, -1, -1, -1, $WS_EX_ACCEPTFILES)
    ;GUISetOnEvent($GUI_EVENT_CLOSE,"_CI_CloseFunc")
    GUICtrlCreateGroup("", 5, 1, 375, 40)
    GUICtrlCreateGroup("", 5, 50, 375, 350)
    Local $_CI_hFile = GUICtrlCreateInput($_CI_FileName, 12,  15, 325, 16, -1, $WS_EX_STATICEDGE)
    GUICtrlSetState(-1, $GUI_DROPACCEPTED)
    GUICtrlSetTip(-1, "You can drop files from shell here...")
    Local $_CI_hStatus = GUICtrlCreateInput("", 90, 49, 200, 16, $ES_READONLY, $WS_EX_STATICEDGE)
    Local $_CI_hFileSel = GUICtrlCreateButton("...", 345,  14, 26, 18)
    ;GUICtrlSetOnEvent(-1,"_CI_LoadButton")
    Local $_CI_Next = GUICtrlCreateButton("&Weiter -|>",310,410)
    ;GUICtrlSetOnEvent(-1,"_CI_Next")
    Local $_CI_Back = GUICtrlCreateButton("<|- &Zurück",20,410)
    ;GUICtrlSetOnEvent(-1,"_CI_Back")
    Local $_CI_OK = GUICtrlCreateButton("Icon wählen:",120,410)
    ;GUICtrlSetOnEvent(-1,"_CI_CloseFunc")
    GUICtrlSetState(-1,$GUI_DISABLE)
    Local $_CI_Icon = GUICtrlCreateIcon("",0,190,404,32,32)
    
    For $iCntRow = 0 to 4
        For $iCntCol = 0 to 5
            $iCurIndex = $iCntRow * 6 + $iCntCol
            $_CI_IconRadios[$iCurIndex] = GUICtrlCreateRadio("", 55 * $iCntCol + 25, 65 * $iCntRow + 75, 45, 45,$BS_ICON+$BS_PUSHLIKE)
;~             GUICtrlSetImage(-1,@SystemDir & "\shell32.dll",-2)
            ;$ahIcons[$iCurIndex]  = GUICtrlCreateIcon($glFilename, 0, 60 * $iCntCol + 25, 70 * $iCntRow + 80)
            ;GUICtrlSetOnEvent(-1,"_CI_SelectedIcon")
            $_CI_Labels[$iCurIndex] = GUICtrlCreateLabel("1", 55 * $iCntCol+12, 65 * $iCntRow + 120, 58, 20, $SS_CENTER)
            GUICtrlSetBkColor(-1,$GUI_BKCOLOR_TRANSPARENT )
        Next
    Next
    
    _CI_NewFileLoad($_CI_FileName,$_CI_IconCount, $_CI_hFile)
    _CI_Update($_CI_IconRadios, $_CI_Labels, $_CI_hStatus, $_CI_StartIndex, $_CI_IconCount, $_CI_FileName, $_CI_SelectedIconName)
    GUISetState ()       ; will display an  dialog box with 1 checkbox
    ; Run the GUI until the dialog is closed
    While 1
        $gMsg = GUIGetMsg()
        Switch $gMsg
            Case $_CI_IconRadios[0] To $_CI_IconRadios[29]
                For $i = 0 To 29
                    If GUICtrlRead($_CI_IconRadios[$i]) = $GUI_CHECKED Then
                        $_CI_SelectedIconName = 1*GUICtrlRead($_CI_Labels[$i])        
                        GUICtrlSetImage($_CI_Icon,$_CI_FileName,$_CI_SelectedIconName)
                        GUICtrlSetState($_CI_OK,$GUI_ENABLE)
                        ExitLoop
                    EndIf
                Next
            
            Case $_CI_hFileSel
                $_CI_NewFile = _CI_NewFileLoad( _ 
                                    FileOpenDialog("Select Icon file:", GUICtrlRead($_CI_hFile), "Icon-Files (*.exe;*.dll;*.ocx;*.icl;*.ico)") _ 
                                    ,$_CI_IconCount, $_CI_hFile)
                    If Not ($_CI_NewFile == -1) Then
                        $_CI_FileName = $_CI_NewFile
                        GUICtrlSetState($_CI_Back,$GUI_DISABLE)
                        GUICtrlSetState($_CI_OK,$GUI_DISABLE)
                        $_CI_StartIndex = 1
                        $_CI_SelectedIconName = 0
                        GUICtrlSetImage($_CI_Icon,"")
                        _CI_Update($_CI_IconRadios, $_CI_Labels, $_CI_hStatus, $_CI_StartIndex, $_CI_IconCount, $_CI_FileName, $_CI_SelectedIconName)
                    EndIf
            
            Case $_CI_Back
                If $_CI_StartIndex - 30 >= 0 Then $_CI_StartIndex -= 30
                If $_CI_StartIndex - 30 < 0 Then 
                    GUICtrlSetState($_CI_Back,$GUI_DISABLE)
                EndIf
                GUICtrlSetState($_CI_Next,$GUI_ENABLE)
                _CI_Update($_CI_IconRadios, $_CI_Labels, $_CI_hStatus, $_CI_StartIndex, $_CI_IconCount, $_CI_FileName, $_CI_SelectedIconName)
            
            Case $_CI_Next
                If $_CI_StartIndex + 30 <= $_CI_IconCount Then $_CI_StartIndex += 30
                If $_CI_StartIndex + 30 > $_CI_IconCount Then 
                        GUICtrlSetState($_CI_Next,$GUI_DISABLE)
                EndIf
                GUICtrlSetState($_CI_Back,$GUI_ENABLE)
                _CI_Update($_CI_IconRadios, $_CI_Labels, $_CI_hStatus, $_CI_StartIndex, $_CI_IconCount, $_CI_FileName, $_CI_SelectedIconName)
            
            Case $GUI_EVENT_CLOSE
                SetError(1)
                ExitLoop
            Case $_CI_OK
                Local $arTemp[2] = [$_CI_FileName,$_CI_SelectedIconName]
                ExitLoop
        EndSwitch
    Wend
    
    GUIDelete($_CI_hGui)
    Opt("GuiOnEventMode",$_CI_oldEventMode)
    Return $arTemp
EndFunc

Func _CI_Update(ByRef $_CI_IconRadios, ByRef $_CI_Labels, $_CI_hStatus, $_CI_StartIndex,ByRef $_CI_IconCount, $_CI_FileName, $_CI_SelectedIconName)
    For $iCntRow = 0 to 4
        For $iCntCol = 0 to 5
            $iCurIndex = $iCntRow * 6 + $iCntCol
            If ($iCurIndex + $_CI_StartIndex) > $_CI_IconCount Then
                GUICtrlSetState($_CI_IconRadios[$iCurIndex], $GUI_HIDE)
                GUICtrlSetState($_CI_Labels[$iCurIndex], $GUI_HIDE)
            Else
                GUICtrlSetState($_CI_IconRadios[$iCurIndex], $GUI_SHOW)
                GUICtrlSetState($_CI_Labels[$iCurIndex], $GUI_SHOW)
                GUICtrlSetState($_CI_IconRadios[$iCurIndex],$GUI_UNCHECKED)
                GUICtrlSetImage($_CI_IconRadios[$iCurIndex], $_CI_FileName, -($_CI_StartIndex + $iCurIndex))
                GUICtrlSetData($_CI_Labels[$iCurIndex], -($_CI_StartIndex + $iCurIndex))
                If -($_CI_StartIndex + $iCurIndex) = $_CI_SelectedIconName Then GUICtrlSetState($_CI_IconRadios[$iCurIndex],$GUI_CHECKED)
            EndIf
        Next
    Next
    GUICtrlSetData($_CI_hStatus, "Icons "& $_CI_StartIndex & "-"& _CI_MyMin(($_CI_StartIndex+ 29), $_CI_IconCount)& " von " & $_CI_IconCount _ 
                                & "  |  Seite "& Ceiling(($_CI_StartIndex)/30)& "von " & Ceiling($_CI_IconCount/30))
EndFunc

Func _CI_NewFileLoad($sTmpFile, ByRef $_CI_IconCount, $_CI_hFile)
    If Not FileExists($sTmpFile) Then Return -1
    If @error Then Return -1
    ;$glFileName = $sTmpFile
    GUICtrlSetData($_CI_hFile, $sTmpFile)
    $_CI_iStartIndex = 1
    $_CI_IconCount =  _GetIconCount($sTmpFile)
    Return $sTmpFile
EndFunc


; Function by YDY (Lazycat)
Func _GetIconCount($sFilename)
    Local $iCount= DllCall("Shell32", "int", "ExtractIconEx", "str", $sFilename, "int", -1, "ptr", 0, "ptr", 0, "int", 1)
    If not @error Then Return $iCount[0]
    Return 0
EndFunc

Func _CI_MyMin($1,$2)
    If Number($1) < Number($2) Then 
        Return Number($1)
    Else
        Return Number($2)
    EndIf
EndFunc

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

large script

I saw that script before on this forum, but that does a lot more than just extracting one icon. Of course I could work myself trough the code and all includes you posted, but I wondered if anyone did that before and could give me the (undoubtly briefer) code to supply me with (only) the first icon of the exe chosen... Edited by maroesjk

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

hi

see my next topic

Edited by nobbe

Share this post


Link to post
Share on other sites

the solution now

;
; icon to JPEG & PNG converter - use first icon in EXE only 
; based upon progandy's scripts
;
; nobbe 2008
;
#include <GDIPlus.au3>

$filename = "c:\Programme\8start Launcher\8start.exe"
$iconnumber = 0 ;
;; 

$Ret = DllCall("shell32","long","ExtractAssociatedIcon","int",0,"str",$filename,"int*",$iconnumber)
$hIcon = $Ret[0]
_GDIPlus_Startup()
        $pBitmap = DllCall($ghGDIPDll,"int","GdipCreateBitmapFromHICON", "ptr",$hIcon, "int*",0)
        $pBitmap = $pBitmap[2]
_GDIPlus_ImageSaveToFile($pBitmap, @ScriptDir & "\Test.jpg")
_GDIPlus_ImageSaveToFile($pBitmap, @ScriptDir & "\Test.png")
_GDIPlus_ImageDispose($pBitmap)
_GDIPlus_Shutdown()
_WinAPI_DestroyIcon($Ret[0])

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

the solution now

[removed script]

Thanx for that, but it still doesn't give me an *.ico-file... Edited by maroesjk

Share this post


Link to post
Share on other sites

GEEEEEZ it cant be SO HARD to find a png2ico tool then ??

http://www.winterdrache.de/freeware/png2ico/

png2ico - PNG to icon converter (Linux, Unix, GNU, Windows, ...)

Converts PNG files to Windows icon resource files. If you're looking for a program to create a favicon.ico for your website, look no further. If you need instructions or don't even know what a favicon is, check out my short tutorial on how to create and install a favicon.ico.

Share this post


Link to post
Share on other sites

GEEEEEZ it cant be SO HARD to find a png2ico tool then ??

No, but as I stated in my the opening of this thread: I want my AutoIt Script to get me the first icon of the exe "without the help of external programs". I can't imagine that this isn't possible one way or another...

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I recently bumped into a topic/post by Smashly on extracting icons from files. I decided to cross-post here in case someone would find this thread, but not Smashly's...

I posted a somewhat modified script here before, which only extracts the first icon. But now I think that referring to Smashly's work is better...

Edited by maroesjk

Share this post


Link to post
Share on other sites

Few problems in your code..

FileWrite(FileOpen($IconFile, 18), $HeaderString)

Not sure but I think your leaving the file handle open.

I could be wrong, but since your giving FileWrite a handle to a file it's a good practice to close the handle when finished.

Your not freeing the loadlibrary when your finished with it.

If you call your modded function mutiple times in a script then memory usage will climb until the script is exited.

Trivial but also should clear the $aEN[1] array before leaving the function.

It uses minimal memory but leaving it full when the function has finished seems not memory friendly as every bit helps.

To each his own, but I feel as if you've butchered my code not improved it.. lol

Cheers

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

You're right about the simplifications in the code. I agree that calling the simplified code multiple times does increase the memory-usage, but I am only calling the function once or twice... I do think, in general, that your code is beter. However, the simplifications removed quite a few lines and the function as posted before worked fine for my needs.

I decided to delete the code posted before because of your comments. It would be best if people just use yours...

One small question though: won't adding code to clear the $aEN[1] array cost more bytes then those released by clearing it?

Edited by maroesjk

Share this post


Link to post
Share on other sites

You're right about the simplifications in the code. I agree that calling the simplified code multiple times does increase the memory-usage, but I am only calling the function once or twice... I do think, in general, that your code is beter. However, the simplifications removed quite a few lines and the function as posted before worked fine for my needs.

I decided to delete the code posted before because of your comments. It would be best if people just use yours...

One small question though: won't adding code to clear the $aEN[1] array cost more bytes then those released by clearing it?

For the $aEN[1] question no not really all you'd need to do is Dim $aEN[1] to reset the array to empty.

Please don't take offense by my previous post about the your modded function it was really only meant to be constructive, but when I re- read my post it sort of comes off as being an ass (which it wasn't meant to be).

It's always good habit to try an optimize your code when writing it, even the small things make a difference in you future style of writing more code. By all means the code I write isn't that great or optimized even though I always have it mind to keep it lean an clean but it usually ends up being bloated and overbearing .. lol

What is important is your code does what you need it to.

Rewriting code in you own way is always a better way of understanding and making it better in the long run.

Cheers

Share this post


Link to post
Share on other sites

I looked throught the DllCall examples for "ExtractAssociatedIcon" and they are all point to "Shell32" which is not what I need. I am trying to get the icon associated with the program that is required to open a certain file type. Example: If I have a .txt file the Notepad icon would have to be extracted and placed on a button. Anyone got the answer? Thanks...


“No other God have I but Thee; born in a manger, died on a tree.” Martin Luther

Share this post


Link to post
Share on other sites

Found it:

$prog = _WinAPI_FindExecutable($filename)
GUICtrlSetImage($button, $prog, 1, 0)


“No other God have I but Thee; born in a manger, died on a tree.” Martin Luther

Share this post


Link to post
Share on other sites

I looked throught the DllCall examples for "ExtractAssociatedIcon" and they are all point to "Shell32" which is not what I need. I am trying to get the icon associated with the program that is required to open a certain file type. Example: If I have a .txt file the Notepad icon would have to be extracted and placed on a button. Anyone got the answer? Thanks...

Look at _WinAPI_ShellExtractAssociatedIcon() in WinAPIEx UDF

Share this post


Link to post
Share on other sites

Look at _WinAPI_ShellExtractAssociatedIcon() in WinAPIEx UDF

Gave it a try, but it only returns the icons if it has the .exe's full path. See my previous post.

“No other God have I but Thee; born in a manger, died on a tree.” Martin Luther

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  
Followers 0