Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как засунуть длл в ресурсы файла, а потом использовать из длл функции?  (Прочитано 14344 раз)
0 Пользователей и 3 Гостей смотрят эту тему.
monrus
Опытный

ru
Offline Offline

« : 09-12-2005 20:55 » 

Как засунуть длл в ресурсы файла, а потом использовать из длл функции?
Записан
zubr
Гость
« Ответ #1 : 10-12-2005 08:05 » 

Цитата
Сохранение и выдёргивание ресурсов в DLL или EXE?
 
Иногда возникает необходимость вшить ресурсы в исполняемый файл Вашего приложения (например чтобы предотвратить их случайное удаление пользователем, либо, чтобы защитить их от изменений). Данный пример показывает как вшить любой файл как ресурс в EXE-шнике.

Далее рассмотрим, как создать файл ресурсов, содержащий корию какого-либо файла. После создания такого файла его можно легко прицепить к Вашему проекту директивой {$R}. Файл ресурсов, который мы будем создавать имеет следующий формат:

+ заголовок
+ заголовок для нашего RCDATA ресурса
+ собственно данные - RCDATA ресурс

В данном примере будет показано, как сохранить в файле ресурсов только один файл, но думаю, что так же легко Вы сможете сохранить и несколько файлов.

Заголовок ресурса выглядит следующим образом:

TResHeader = record 
  DataSize: DWORD;        // размер данных       
  HeaderSize: DWORD;      // размер этой записи 
  ResType: DWORD;         // нижнее слово = $FFFF => ordinal 
  ResId: DWORD;           // нижнее слово = $FFFF => ordinal 
  DataVersion: DWORD;     // * 
  MemoryFlags: WORD; 
  LanguageId: WORD;       // * 
  Version: DWORD;         // * 
  Characteristics: DWORD; // * 
end; 

Поля помеченны звёздочкой Мы не будем использовать.

Приведённый код создаёт файл ресурсов и копирует его в данный файл:

procedure CreateResourceFile( 
  DataFile, ResFile: string;  // имена файлов 
  ResID: Integer              // id ресурсов 
); 
var 
  FS, RS: TFileStream; 
  FileHeader, ResHeader: TResHeader; 
  Padding: array[0..SizeOf(DWORD)-1] of Byte; 
begin 

  { Open input file and create resource file } 
  FS := TFileStream.Create(  // для чтения данных из файла
    DataFile, fmOpenRead); 
  RS := TFileStream.Create(  // для записи файла ресурсов 
    ResFile, fmCreate); 

  { Создаём заголовок файла ресурсов - все нули, за исключением 
    HeaderSize, ResType и ResID } 
  FillChar(FileHeader, SizeOf(FileHeader), #0); 
  FileHeader.HeaderSize := SizeOf(FileHeader); 
  FileHeader.ResId := $0000FFFF; 
  FileHeader.ResType := $0000FFFF; 

  { Создаём заголовок данных для RC_DATA файла 
    Внимание: для создания более одного ресурса необходимо 
    повторить следующий процесс, используя каждый раз различные 
    ID ресурсов } 
  FillChar(ResHeader, SizeOf(ResHeader), #0); 
  ResHeader.HeaderSize := SizeOf(ResHeader); 
  // id ресурса - FFFF означает "не строка!" 
  ResHeader.ResId := $0000FFFF or (ResId shl 16); 
  // тип ресурса - RT_RCDATA (from Windows unit) 
  ResHeader.ResType := $0000FFFF 
    or (WORD(RT_RCDATA) shl 16); 
  // размер данных - есть размер файла 
  ResHeader.DataSize := FS.Size; 
  // Устанавливаем необходимые флаги памяти 
  ResHeader.MemoryFlags := $0030; 

  { Записываем заголовки в файл ресурсов } 
  RS.WriteBuffer(FileHeader, sizeof(FileHeader)); 
  RS.WriteBuffer(ResHeader, sizeof(ResHeader)); 

  { Копируем файл в ресурс } 
  RS.CopyFrom(FS, FS.Size); 

  { Pad data out to DWORD boundary - any old 
    rubbish will do!} 
  if FS.Size mod SizeOf(DWORD) <> 0 then 
    RS.WriteBuffer(Padding, SizeOf(DWORD) - 
      FS.Size mod SizeOf(DWORD)); 

  { закрываем файлы } 
  FS.Free; 
  RS.Free; 
end; 

Данный код не совсем красив, и отсутствует обработка ошибок. Правильнее будет создать класс, включающий в себя данный пример.



Извлечение ресурсов из EXE
теперь рассмотрим пример, показывающий, как извлекать ресурсы из исполняемого модуля.

Вся процедура заключается в создании потока ресурса, создании файлового потока и копировании из потока ресурса в поток файла.

procedure ExtractToFile(Instance:THandle; ResID:Integer; ResType, FileName:String); 
var 
  ResStream: TResourceStream; 
  FileStream: TFileStream; 
begin 
  try 
    ResStream := TResourceStream.CreateFromID(Instance, ResID, pChar(ResType)); 
    try 
      //if FileExists(FileName) then 
        //DeleteFile(pChar(FileName)); 
      FileStream := TFileStream.Create(FileName, fmCreate); 
      try 
        FileStream.CopyFrom(ResStream, 0); 
      finally 
        FileStream.Free; 
      end; 
    finally 
      ResStream.Free; 
    end; 
  except 
    on E:Exception do 
    begin 
      DeleteFile(FileName); 
      raise; 
    end; 
  end; 
end; 

Всё, что требуется, это получить Instance exe-шника или dll (у Вашего приложения это Application.Instance или Application.Handle, для dll Вам прийдётся получить его самостоятельно Улыбаюсь

ResID тот же самый ID , который был присвоен ресурсу

ResType WAVEFILE, BITMAP, CURSOR, CUSTOM - это типы ресурсов, с которыми возможно работать, но у меня получилось успешно проделать процедуру только с CUSTOM

FileName - это имя файла, который мы хотим создать из ресурса

Взято из http://forum.sources.ru
Также создать файл ресурса можно с помощью борландской утилиты BRCC32.EXE. Здесь я это описывать не буду, все это хорошо описано в многочисленных FAQ.

Чтобы пользоваться функциями dll из ресурса, надо после выдергивания ее из ресурса сохранить в каталоге программы, или в системной папке Windows, а затем пользоваться как в традиционных случаях.
« Последнее редактирование: 10-12-2005 08:18 от zubr » Записан
monrus
Опытный

ru
Offline Offline

« Ответ #2 : 10-12-2005 18:03 » new

то есть сохранять из ресурса опять на диске? А по другому нельзя? В памяти , например
Записан
Oldy
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 10-12-2005 18:48 » 

Можно и в памяти, в виртуальной. См. "File Mapping".
Записан

С уважением, Oldy.
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #4 : 10-12-2005 20:42 » 

Вопрос на засыпку: А зачем это нужно.
IMHO библиотеки нужно писать  в двух случаях
1. Библиотеки Плугины. Т.е. от подключенных библиотек будет зависеть функциональность приложения.
2. Расшаринные библиотеки. Когда одну и туже библиотеку будут использовать несколько приложений.

Если верить Рихтеру. Когда Винда считывает библиотеку в память, она сначало производит полную настройку всех ссылок в библиотеке. Затем в зависимости от параметров библиотеки запускает функцию DllMain с параметром DLL_PROCESS_ATTACH. Инструментов самой Винды, по считыванию из ресурсов библиотеки я лично не знаю. Конечно можно извратится и разработать такие самому. Только зачем это нужно?
Если ты не хочеш показывать библиотеку, и при этом использовать ее. Возьми всю функциональную часть библиотеки перенеси в основной проект. Намного меньше головных болей.
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
monrus
Опытный

ru
Offline Offline

« Ответ #5 : 10-12-2005 22:50 » 

Нет, просто у меня есть библиотека, с помощью которой музыка проигрывается и муз.файл. Муз.файл я засунул в ресурсы, проигрывается он из ресурсов, но использует эту внешнюю длл. Это как-то неполноценно. Раз муз.файл в ресурсах, так пусть и длл тоже будет сидеть в ресурсах. Я только этого хочу.
Записан
zubr
Гость
« Ответ #6 : 11-12-2005 09:41 » 

Ну можно попробовать содержимое потока TResourceStream (то есть dll выдранная из ресурса) загнать в память процесса, с помощью функции WriteProcessMemory, а уже оттуда юзать нужные функции dll. Сам, практически такого не делал.
З.Ы. Проще все таки при открытии проги загонять dll в папку System32, а при закрытии удалять оттуда. Обычный юзверь и не заметит Улыбаюсь
« Последнее редактирование: 11-12-2005 09:47 от zubr » Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #7 : 14-12-2005 07:22 » 

в старые добрые времена можно было слинковать с экзешником любой файл, и при эхтом работать с ним, как с обычным экзешником. дилалось это через объектные файлы, и существовала тулза, которая любой бинарник конвертила в *.obj, а потом специальной директивой можно было подключить такой файл к проекту. я сильно подозреваю, что никто не запрещает это делать и по сей день Ага
Записан

zubr
Гость
« Ответ #8 : 14-12-2005 18:23 » 

На линкуемый *.obj в дельфях куча ограничений, как-то пробовал такое, только потратил кучу времени, за которую можно было самому несколько раз данный модуль написать.
Записан
zubr
Гость
« Ответ #9 : 25-12-2005 20:24 » 

Вот случайно нашел статью на данную тему.

* peloader.zip (31.9 Кб - загружено 1141 раз.)
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines