|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » AutoIt » [решено] Интересная проблема при выдирании иконки из exe |
|
[решено] Интересная проблема при выдирании иконки из exe
|
Пользователь Сообщения: 62 |
Профиль | Отправить PM | Цитировать
Не много раньше я открывал тему "Вытащить из .exe или .dll иконку "
Creat0R Предложил мне функцию. FileExtractIcon("shell32.dll", @DesktopDir & "\Icon.ico", -20) Одним из недостатков этой функции был тот что иконки на выходе получаются на чёрном фоне. Тогда beve предложил более сложную функцию которую впоследствии Creat0R оптимизировав её убрал всё лишние, на выходе получилась функция которая нормально справлялась со своей работой. До тех пор пока мне не попался случайно файл crack.exe и моя програмка которую я делаю при попытке выдрать эту иконку тут же гаснет, я испытывал на многих файлах и 99 из 100 функция работает отлично В SciTE при отладке этой функции пишет ошибку Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight($AHDR[$I - 1], 4)))) Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight(^ ERROR Кстати професиональная прога Articons Pro хоть и не гасла но тоже отказывалась вытаскивать эти иконки (их кстати там две) А вот первая функция которую мне предложил Creat0R FileExtractIcon("crack.exe", @DesktopDir & "\Icon.ico", -1) Вытащила их без проблем только как я уже говорил на чёрном фоне. Только прога Koda в которой есть фишка которая подставляет иконки в вашу программу и там можно эту иконку вытащить, справилась с этим crack.exe без проблем.Но как узнать как она это сделала? Всё таки интересно что за ошибка вылезает в этой функции Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight($AHDR[$I - 1], 4)))) Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight(^ ERROR И она напрочь отказывается работать с этим crack.exe Ещё раз повторю 99 из 100 функция работает отлично. Файл crack.exe Прилагаю. #include <WinAPI.au3> Global $aEN[1] $sSrc = @SystemDir & "\shell32.dll" ;"crack.exe" $sOut = @DesktopDir & "\MyIcon.ico" _FileExtractIcon($sSrc, -1, $sOut) Func _FileExtractIcon($sINFILE, $iICON, $sOUTICO, $iPATH = 0, $iSaveAsPng = 0) Local Const $RT_GROUP_ICON = 14 Local $hINST, $iGN = "", $HFIND, $aSIZE, $hLOAD, $HLOCK, $TRES, $sDATA, $aRet[2] If Not FileExists($sINFILE) And Not IsPtr($sINFILE) Then Return SetError(1, 0, 0) If Not IsInt($iICON) Then Return SetError(2, 0, 0) If IsPtr($sINFILE) Then $hINST = $sINFILE Else $hINST = _WinAPI_LoadLibraryEx($sINFILE, 2) If Not $hINST Then Return SetError(3, 0, 0) EndIf If Not IsPtr($hINST) Then Return SetError(3, 0, 0) __ResourceEnumNames($hINST, $RT_GROUP_ICON) If @error Then _WinAPI_FreeLibrary($hINST) Return SetError(4, 0, 0) EndIf For $I = 1 To $aEN[0] If $I = StringReplace($iICON, "-", "") Then $iGN = $aEN[$I] ExitLoop EndIf Next If $iGN = "" Then _WinAPI_FreeLibrary($hINST) Return SetError(5, 0, 0) EndIf $HFIND = DllCall("kernel32.dll", "int", "FindResourceA", "int", $hINST, "str", $iGN, "long", $RT_GROUP_ICON) If $HFIND[0] = 0 Then _WinAPI_FreeLibrary($hINST) Return SetError(6, 0, 0) EndIf $aSIZE = DllCall("kernel32.dll", "dword", "SizeofResource", "int", $hINST, "int", $HFIND[0]) If $aSIZE[0] = 0 Then _WinAPI_FreeLibrary($hINST) Return SetError(7, 0, 0) EndIf $hLOAD = DllCall("kernel32.dll", "int", "LoadResource", "int", $hINST, "int", $HFIND[0]) If $hLOAD[0] = 0 Then _WinAPI_FreeLibrary($hINST) Return SetError(8, 0, 0) EndIf $HLOCK = DllCall("kernel32.dll", "int", "LockResource", "int", $hLOAD[0]) If $HLOCK[0] = 0 Then _WinAPI_FreeLibrary($hINST) Return SetError(9, 0, 0) EndIf $TRES = DllStructCreate("byte[" & $aSIZE[0] & "]", $HLOCK[0]) If Not IsDllStruct($TRES) Then _WinAPI_FreeLibrary($hINST) Return SetError(10, 0, 0) EndIf $sDATA = DllStructGetData($TRES, 1) If $sDATA = "" Then _WinAPI_FreeLibrary($hINST) Return SetError(11, 0, 0) EndIf __FreeResource($hLOAD[0]) If Not IsPtr($sINFILE) Then _WinAPI_FreeLibrary($hINST) Dim $aEN[1] $aRet[0] = $sINFILE $aRet[1] = $sDATA ;_Exticondata() Local $aID = $aRet Local Const $RT_ICON = 3 Local $hINST, $AHDR, $aRet[1][2] If Not IsArray($aID) Then Return SetError(1, 0, 0) If Not FileExists($aID[0]) And Not IsPtr($aID[0]) Then Return SetError(2, 0, 0) If IsPtr($aID[0]) Then $hINST = $aID[0] Else $hINST = _WinAPI_LoadLibraryEx($aID[0], 2) If Not $hINST Then Return SetError(3, 0, 0) EndIf If Not IsPtr($hINST) Then Return SetError(3, 0, 0) $aRet[0][0] = Dec(__Rb(StringMid($aID[1], 11, 4))) ReDim $aRet[$aRet[0][0] + 1][2] $AHDR = StringRegExp(StringTrimLeft(BinaryMid($aID[1], 7), 2), "(.{28})", 3) For $I = 1 To $aRet[0][0] Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight($AHDR[$I - 1], 4)))) $aRet[$I][0] = StringTrimRight($AHDR[$I - 1], 4) $aRet[$I][1] = $AGID[1] __FreeResource($AGID[0]) Next If Not IsPtr($aID[0]) Then _WinAPI_FreeLibrary($hINST) ;_Createiconfile($aID, $aSEL, $sOUTICO, $iPATH = 0, $iSaveAsPng = 0) Local $aSEL = $iICON $aID = $aRet If Not IsArray($aID) Then Return SetError(1, 0, 0) Local $iCNT, $sHDR, $OFFSET, $sDBYTE, $iMICON = "", $FO, $FW, $eSEL[$aID[0][0]], $iCRT = 18 If $iPATH <> 0 Then $iCRT = 26 If Not IsArray($aSEL) Then For $I = 0 To UBound($eSEL) - 1 $eSEL[$I] = $I + 1 Next $aSEL = $eSEL EndIf If UBound($aSEL) = 1 And StringInStr(StringTrimLeft($aID[$aSEL[0]][1], 2), "504E47") Then If $iSaveAsPng Then $sOUTICO = StringReplace($sOUTICO, ".ico", ".png") EndIf $iCNT = UBound($aSEL) $sHDR = "0x00000100" & __Rb(Hex($iCNT, 4)) $OFFSET = ($iCNT * 16) + 6 For $I = 0 To UBound($aSEL) - 1 $sDBYTE = Dec(__Rb(StringMid($aID[$aSEL[$I]][0], 17, 8))) $sHDR &= $aID[$aSEL[$I]][0] & __Rb(Hex($OFFSET)) $OFFSET += $sDBYTE If StringRight($sOUTICO, 4) = ".png" Then $sHDR = "" $iMICON &= $aID[$aSEL[$I]][1] Else $iMICON &= StringTrimLeft($aID[$aSEL[$I]][1], 2) EndIf Next $FO = FileOpen($sOUTICO, $iCRT) If $FO = -1 Then Return SetError(2, 0, 0) $FW = FileWrite($FO, $sHDR & $iMICON) If $FW = 0 Then FileClose($FO) Return SetError(3, 0, 0) EndIf FileClose($FO) Return SetError(0, 0, 1) EndFunc Func __FreeResource($HGLBRESOURCE) DllCall("kernel32.dll", "int", "FreeResource", "int", $HGLBRESOURCE) EndFunc Func __GetIconData($hMODULE, $iON) Local Const $RT_ICON = 3 Local $HFIND, $aSIZE, $hLOAD, $HLOCK, $TRES, $aRet[2] $HFIND = DllCall("kernel32.dll", "int", "FindResourceA", "int", $hMODULE, "str", "#" & $iON, "long", $RT_ICON) $aSIZE = DllCall("kernel32.dll", "dword", "SizeofResource", "int", $hMODULE, "int", $HFIND[0]) $hLOAD = DllCall("kernel32.dll", "int", "LoadResource", "int", $hMODULE, "int", $HFIND[0]) $HLOCK = DllCall("kernel32.dll", "int", "LockResource", "int", $hLOAD[0]) $TRES = DllStructCreate("byte[" & $aSIZE[0] & "]", $HLOCK[0]) $aRet[0] = $HLOCK[0] $aRet[1] = DllStructGetData($TRES, 1) Return $aRet EndFunc Func __Rb($sBYTE) Local $AX = StringRegExp($SBYTE, "(.{2})", 3), $SX = "" For $I = UBound($AX) - 1 To 0 Step -1 $SX &= $AX[$I] Next Return $SX EndFunc Func __ResourceEnumNames($hMODULE, $iTYPE) Local $aRet, $stCB If Not IsPtr($hMODULE) Then Return SetError(1, 0, 0) $stCB = DllCallbackRegister("__ResourceEnumNames_Proc", "int", "int_ptr;int_ptr;int_ptr;int_ptr") $aRet = DllCall("kernel32.dll", "int", "EnumResourceNamesW", "ptr", $hMODULE, "int", $iTYPE, "ptr", DllCallbackGetPtr($stCB), "ptr", 0) DllCallbackFree($stCB) If $aRet[0] <> 1 Then Return SetError(2, 0, 0) Return SetError(0, 0, 1) EndFunc Func __ResourceEnumNames_Proc($hMODULE, $pTYPE, $pNAME, $lPARAM) Local $aSIZE = DllCall("kernel32.dll", "int", "GlobalSize", "ptr", $pNAME), $tBUF If $aSIZE[0] Then $tBUF = DllStructCreate("wchar[" & $aSIZE[0] & "]", $pNAME) ReDim $aEN[UBound($aEN) + 1] $aEN[0] += 1 $aEN[UBound($aEN) - 1] = DllStructGetData($tBUF, 1) Else ReDim $aEN[UBound($aEN) + 1] $aEN[0] += 1 $aEN[UBound($aEN) - 1] = "#" & $pNAME EndIf Return 1 EndFunc |
|
Отправлено: 03:17, 23-07-2010 |
Must AutoIt Сообщения: 3054
|
Профиль | Сайт | Отправить PM | Цитировать Цитата assch:
Вот исправленная версия, ошибок не будет, но иконку не вытаскивает, мне кажется в этом случае можно использовать упрощонную версию, там всё ровно не заметно чёрного фона: #include-once #include <GDIPlus.au3> #include <WinAPI.au3> Global $a__EN[1] $sSrc = @DesktopDir & "\crack.exe" $sDest = @DesktopDir & "\crack.ico" $iRet = _FileExtractIcon($sSrc, -1, $sDest) If @error Then _FileExtractIconSimple($sSrc, $sDest, -1) Func _FileExtractIcon($sInFile, $iIcon, $sOutIco, $iPath = 0) Local Const $LOAD_LIBRARY_AS_DATAFILE = 0x00000002 Local Const $RT_ICON = 3 Local Const $RT_GROUP_ICON = 14 Local $hInst, $iGN = "", $sData, $sDByte, $sHdr, $aHdr, $iCnt, $Offset, $FO, $FW, $iCrt = 18 If $iPath = 1 Then $iCrt = 26 ;+8, to create directory structure If Not FileExists($sInFile) Then Return SetError(1, 0, 0) If Not IsInt($iIcon) Then Return SetError(2, 0, 0) $hInst = _LoadLibraryEx($sInFile, $LOAD_LIBRARY_AS_DATAFILE) If Not $hInst Then Return SetError(3, 0, 0) _ResourceEnumNames($hInst, $RT_GROUP_ICON) For $i = 1 To $a__EN[0] If $i = StringReplace($iIcon, "-", "") Then $iGN = $a__EN[$i] ExitLoop EndIf Next Dim $a__EN[1] If $iGN = "" Then _FreeLibrary($hInst) Return SetError(4, 0, 0) EndIf $sData = _GetIconResource($hInst, $iGN, $RT_GROUP_ICON) If @error Then _FreeLibrary($hInst) Return SetError(5, 0, 0) EndIf $sHdr = BinaryMid($sData, 1, 6) $aHdr = StringRegExp(StringTrimLeft(BinaryMid($sData, 7), 2), "(.{28})", 3) $iCnt = UBound($aHdr) $Offset = ($iCnt * 16) + 6 For $i = 0 To $iCnt - 1 $sDByte = Dec(_StringReverseBytes(StringMid($aHdr[$i], 17, 8))) $sHdr &= StringTrimRight($aHdr[$i], 4) & _StringReverseBytes(Hex($Offset)) $Offset += $sDByte Next For $i = 0 To $iCnt - 1 $sData = _GetIconResource($hInst, "#" & Dec(_StringReverseBytes(StringRight($aHdr[$i], 4))), $RT_ICON) If @error Then _FreeLibrary($hInst) Return SetError(6, 0, 0) EndIf $sHdr &= StringTrimLeft($sData, 2) Next _FreeLibrary($hInst) $FO = FileOpen($sOutIco, $iCrt) If $FO = -1 Then Return SetError(7, 0, 0) $FW = FileWrite($FO, $sHdr) If $FW = 0 Then FileClose($FO) Return SetError(8, 0, 0) EndIf FileClose($FO) Return SetError(0, 0, 1) EndFunc ;==>_FileExtractIcon Func _FileExtractIconSimple($sSrcFileIcon, $sOutFileIcon, $iIndex = 0) Local $aRet, $hIcon, $pBitmapdll, $pBitmap If $iIndex < 0 Then $iIndex = ($iIndex * -1) EndIf $aRet = DllCall("shell32.dll", "long", "ExtractAssociatedIcon", "int", 0, "str", $sSrcFileIcon, "int*", $iIndex - 1) $hIcon = $aRet[0] _GDIPlus_Startup() $pBitmapdll = DllCall($ghGDIPDll, "int", "GdipCreateBitmapFromHICON", "ptr", $hIcon, "int*", 0) $pBitmap = $pBitmapdll[2] _WinAPI_DestroyIcon($hIcon) _GDIPlus_ImageSaveToFileEx($pBitmap, $sOutFileIcon, "{557CF400-1A04-11D3-9A73-0000F81EF32E}") _GDIPlus_ImageDispose($pBitmap) _GDIPlus_Shutdown() Return 1 Endfunc ; ======================================================================================================== ; Internal Helper Functions from this point on ; ======================================================================================================== Func _GetIconResource($hModule, $sResName, $iResType) Local $hFind, $aSize, $hLoad, $hLock, $tRes, $sRet $hFind = DllCall("kernel32.dll", "int", "FindResource", "int", $hModule, "str", $sResName, "long", $iResType) If @error Or Not $hFind[0] Then Return SetError(1, 0, 0) $aSize = DllCall("kernel32.dll", "dword", "SizeofResource", "int", $hModule, "int", $hFind[0]) If @error Or Not $aSize[0] Then Return SetError(2, 0, 0) $hLoad = DllCall("kernel32.dll", "int", "LoadResource", "int", $hModule, "int", $hFind[0]) If @error Or Not $hLoad[0] Then Return SetError(3, 0, 0) $hLock = DllCall("kernel32.dll", "int", "LockResource", "int", $hLoad[0]) If @error Or Not $hLock[0] Then _FreeResource($hLoad[0]) Return SetError(4, 0, 0) EndIf $tRes = DllStructCreate("byte[" & $aSize[0] & "]", $hLock[0]) If Not IsDllStruct($tRes) Then _FreeResource($hLoad[0]) Return SetError(5, 0, 0) EndIf $sRet = DllStructGetData($tRes, 1) If $sRet = "" Then _FreeResource($hLoad[0]) Return SetError(6, 0, 0) EndIf _FreeResource($hLoad[0]) Return $sRet EndFunc ;==>_GetIconResource Func _LoadLibraryEx($sFile, $iFlag) Local $aRet = DllCall("Kernel32.dll", "hwnd", "LoadLibraryExW", "wstr", $sFile, "hwnd", 0, "int", $iFlag) Return $aRet[0] EndFunc ;==>_LoadLibraryEx Func _FreeLibrary($hModule) DllCall("Kernel32.dll", "hwnd", "FreeLibrary", "hwnd", $hModule) EndFunc ;==>_FreeLibrary Func _FreeResource($hglbResource) DllCall("kernel32.dll", "int", "FreeResource", "int", $hglbResource) EndFunc ;==>_FreeResource ; Just a Reverse string byte function (smashly style..lol) Func _StringReverseBytes($sByte) Local $aX = StringRegExp($sByte, "(.{2})", 3), $sX = '' For $i = UBound($aX) - 1 To 0 Step -1 $sX &= $aX[$i] Next Return $sX EndFunc ;==>_StringReverseBytes Func _ResourceEnumNames($hModule, $iType) Local $aRet, $xCB If Not $hModule Then Return SetError(1, 0, 0) $xCB = DllCallbackRegister('__ResourceEnumNamesProc', 'int', 'int_ptr;int_ptr;int_ptr;int_ptr') $aRet = DllCall('kernel32.dll', 'int', 'EnumResourceNamesW', 'ptr', $hModule, 'int', $iType, 'ptr', DllCallbackGetPtr($xCB), 'ptr', 0) DllCallbackFree($xCB) If $aRet[0] <> 1 Then Return SetError(2, 0, 0) Return SetError(0, 0, 1) EndFunc ;==>_ResourceEnumNames Func __ResourceEnumNamesProc($hModule, $pType, $pName, $lParam) Local $aSize = DllCall('kernel32.dll', 'int', 'GlobalSize', 'ptr', $pName), $tBuf If $aSize[0] Then $tBuf = DllStructCreate('wchar[' & $aSize[0] & ']', $pName) ReDim $a__EN[UBound($a__EN) + 1] $a__EN[0] += 1 $a__EN[UBound($a__EN) - 1] = DllStructGetData($tBuf, 1) Else ReDim $a__EN[UBound($a__EN) + 1] $a__EN[0] += 1 $a__EN[UBound($a__EN) - 1] = "#" & $pName EndIf Return 1 EndFunc ;==>__ResourceEnumNamesProc |
|
------- Отправлено: 15:55, 23-07-2010 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Пользователь Сообщения: 62
|
Профиль | Отправить PM | Цитировать описание ошибки
G:\Documents and Settings\assch\??????? ????\f33.au3 (91) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.: Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight($AHDR[$I - 1], 4)))) Local $AGID = __GetIconData($hINST, Dec(__Rb(StringRight(^ ERROR |
Отправлено: 16:08, 23-07-2010 | #3 |
Must AutoIt Сообщения: 3054
|
Профиль | Сайт | Отправить PM | Цитировать Цитата assch:
|
|
------- Отправлено: 16:16, 23-07-2010 | #4 |
Пользователь Сообщения: 62
|
Профиль | Отправить PM | Цитировать Да в последнем примере этого нет
Просто я дополнил описание ошибки старого примера Простите что ввёл в заблуждение Если вы помните я писал что КОДА справилась без проблем Простите за нескромность А каким алгоритмом она это делает вы не знаете? |
|
Отправлено: 17:06, 23-07-2010 | #5 |
Пользователь Сообщения: 62
|
Профиль | Отправить PM | Цитировать Помните я писал что собираю програмку по данной теме
Так вот с вашей помощью что вышло Правда со старым кодом для выдирания файл прилагаю |
Последний раз редактировалось assch, 23-04-2012 в 01:40. Отправлено: 17:15, 23-07-2010 | #6 |
Ветеран Сообщения: 812
|
Профиль | Отправить PM | Цитировать |
Отправлено: 17:27, 23-07-2010 | #7 |
Участник сейчас на форуме | Участник вне форума | Автор темы | Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Интерфейс - Пропали иконки к *.exe MS-DOS файлам. | alexy | Microsoft Windows 2000/XP | 24 | 08-12-2008 21:40 | |
Почему после перезапуска explorer.exe не все иконки появляются в трее? | Котяра | Хочу все знать | 2 | 05-07-2008 21:36 | |
Интересная проблема! | DarkManX | Непонятные проблемы с Железом | 19 | 14-03-2008 19:06 | |
ИНТЕРЕСНАЯ ПРОБЛЕМА с подключением через Remote Desktop | mao | Microsoft Windows NT/2000/2003 | 19 | 13-06-2006 10:28 | |
Интересная проблема | cheap | Хочу все знать | 2 | 19-09-2002 12:46 |
|