Что нового

Данные, строки Чтение (запись) бинарных данных из (в) файл(а)

musicstashall

Знающий
Сообщения
322
Репутация
7
Возникла необходимость заменить закодированные строчные данные в ресурсах файла, думаю, как это сделать. Данным способом не получилось :acute:
Код:
Global $file_source = FileOpenDialog('Выберите файл', @MyDocumentsDir, 'Файлы ресурсов (*.res;*.rc;*.dcr;*raw)|Все типы (*.*)', 1)
Global $hFile = FileOpen($file_source, 16)
Global $Binary = FileRead($hFile)
ConsoleWrite($Binary & @CR)
Global $Data = BinaryToString($Binary)
ConsoleWrite($Data & @CR)


Файл ресурсов представляет из себя DLL, в котором под типом STRS в бинарном виде имеются строковые данные, разделенные нулевыми байтами. Два варианта:
а) я извлекаю бинарные данные с помощью ResourceHacker или Restorator и читаю их в скрипте
б) читаю данные непосредственно из DLL
Цель: перевести строки на русский и записать в целевой файл.
В архиве: непосредственно DLL и извлеченный ресурс со строками 31200.res
 

Вложения

  • Resources.rar
    2.2 МБ · Просмотры: 5
Последнее редактирование:

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Сам недавно открыл для себя возможности работы с ресурсами...
Код:
#include <WinAPIRes.au3>

Global $sFile = @DesktopDir & '\Source.dll'
Global $sType = 'STRS'
Global $sName = 31200

$sBytes = _ResourceGetStr($sFile, $sType, $sName)

If Not @error Then
    $sStrsOld = BinaryToString($sBytes)
    $aStrs = StringSplit($sStrsOld, Chr(0))
  
    For $i = 1 To $aStrs[0]
        ConsoleWrite($aStrs[$i] & @CRLF)
    Next
  
    $sStrsNew = StringReplace($sStrsOld, '%d elements', BinaryToString(StringToBinary('%d элементов', 4)))
    _ResourceReplaceStr($sFile, $sType, $sName, 1033, $sStrsOld, $sStrsNew)
EndIf

Func _ResourceGetStr($sBinFile, $sType, $sName)
    Local $hInstance = _WinAPI_LoadLibraryEx($sBinFile, $LOAD_LIBRARY_AS_DATAFILE)
  
    ;File not found
    If Not $hInstance Then
        Return SetError(1, 0, 0)
    EndIf
  
    Local $hResource = _WinAPI_FindResource($hInstance, $sType, $sName)
    Local $iSize = _WinAPI_SizeOfResource($hInstance, $hResource)
    Local $hData = _WinAPI_LoadResource($hInstance, $hResource)
    Local $pData = _WinAPI_LockResource($hData)
    Local $tBuffer = DllStructCreate('byte array[' & $iSize & ']', $pData)
    Local $bRes = DllStructGetData($tBuffer, 'array')
  
    _WinAPI_FreeLibrary($hInstance)
    Return $bRes
EndFunc

Func _ResourceReplaceStr($sBinFile, $sType, $sName, $iLang, $sOldStr, $sNewStr, $bResStr = 0)
    If $bResStr = 0 Then
        $bResStr = _ResourceGetStr($sBinFile, $sType, $sName)
      
        If @error Then
            Return SetError(1, 0, 0)
        EndIf
    EndIf
  
    Local $bReplace = StringToBinary(StringReplace(BinaryToString($bResStr), $sOldStr, $sNewStr))
    $tBuffer = DllStructCreate('byte array[' & BinaryLen($bReplace) & ']')
    DllStructSetData($tBuffer, 'array', $bReplace)
  
    Local $hUpdate = _WinAPI_BeginUpdateResource($sBinFile)
    _WinAPI_UpdateResource($hUpdate, $sType, $sName, $iLang, DllStructGetPtr($tBuffer), DllStructGetSize($tBuffer))
    _WinAPI_EndUpdateResource($hUpdate)
  
    Return 1
EndFunc


Тут можно сразу сделать замену по всем строкам, и только один раз сделать замену ресурса в файле.

PS:
Также есть библиотека ResourcesEx UDF, она мне и помогла разобраться с чтением ресурсов.
 
Автор
M

musicstashall

Знающий
Сообщения
322
Репутация
7
Большущее тебе спасибо. Очень помог.
 
Последнее редактирование:
Верх