Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Добавить ресурс в запущенную программу


Автор: Gwire 11.4.2011, 13:10
Тем похожих полно. Но все они о добавлении данных в ресурс до компиляции. 
Не исключено, что есть тема котора решает мою проблему, но среди тех "похожих"... я просто устал их перечитывать.

Предисловие:
Уже разработан и "принят на вооружение" класс (TCustomFormatStr), который загружает язык интерфейса и делает он это из ресурса.
Получается так, в зависимости от того какой файл был добавлен в ресурс до компиляции такой и будет язык интерфейса проекта.
Ресурс который он ищет - "FormatStr". Просто взять и поменять эту логику я не могу.

Задача:
Сделать загрузку  язык интерфейса призапуске программы, а не в момент компиляции.
  Не добавлять файл с языком до компиляции, а держать их отдельно от программы.  [  OK  ]
  Компилировать и запустить программу                                            [  OK  ]
  Добавить ресурс "FormatStr" из файла выбранного пользователем                  [ FAIL ]

Возможно ли вообще добавлять ресурсы уже воврмя работы программы?

Автор: RomanEEP 11.4.2011, 14:15
Думаю что изменять экзешник во время выполнения недопускается. И вообще пытаться загрузить данные в ресурсы, а потом из ресурсов считывать метод прямо говоря кривой. Гораздо лучше сделать класс TCustomFormatStr абстрактным и реализовать наследники, кот позволяют ему работать как с файлами, так и с ресурсами

Автор: Gwire 11.4.2011, 14:49

Цитата(RomanEEP @  11.4.2011,  14:15 Найти цитируемый пост)
Гораздо лучше сделать класс TCustomFormatStr абстрактным 

Истинно так. Но увы я не могу менять это класс "TCustomFormatStr". Всмысле я могу - но нельзя.

А сам экзешник менять не нужно. Нужно динамически подгрузить "файл языка" в ресурс HInstance.



Автор: cat512 12.4.2011, 00:06
Как вариант использовать алгоритм packer-a/unpacker-a, но сложно всё это 

Автор: northener 12.4.2011, 02:20
Цитата(Gwire @  11.4.2011,  14:49 Найти цитируемый пост)
А сам экзешник менять не нужно. Нужно динамически подгрузить "файл языка" в ресурс HInstance.


Ресурс - есть ресурс. Он существует только в файле на диске.

Автор: bems 12.4.2011, 03:55
Если нельзя менять только потому что во многих других местах завязано, то можно изменить минимально - добавить возможность загружать не только из своего HInstance, а из любого. Ну и сделать файлы переводов ресурсными дллками

Также можно перезаписывать ресурс в памяти, но для этого длина нового ресурса не должна превышать длины старого.

Автор: northener 12.4.2011, 04:35
Цитата(bems @  12.4.2011,  03:55 Найти цитируемый пост)
Также можно перезаписывать ресурс в памяти, но для этого длина нового ресурса не должна превышать длины старого.

А вот тут желательно было дать либо ссылку, либо пример. Ибо мне, например, такой вариант пока не встречался.

Автор: bems 12.4.2011, 07:39
northener, дам объяснение на пальцах. LockResource на самом деле возвращает указатель на ресурс, спроецированный на АП процесса вместе со всем исполняемым модулем. По этом адресу и можно перезаписать SizeofResource байт. Атрибуты защиты памяти обычно не позволяют этого сделать, поэтому нужно сперва сделать VirtualProtect этой области.
То что последовательность FindResource-LoadResource-LockResource ничего фактически не загружает, а всего лишь находит указатель на ресурс, присутствующий в АП с самой загрузки модуля, и что это всегда один и тот же указатель для одного и того же ресурса в интервале загрузка модуля-выгрузка модуля нигде не документировано, но подтверждается практикой.

Добавлено через 6 минут и 27 секунд
Не даром же в MSDN сказано что FreeResource не нужна начиная с 32хбитных винд. Во времена х16 не было раздельных адресных пространств, и так появилась такая сложная последовательность работы с ресурсами. А с появлением виртуальных АП ресурс сразу же проецируется, и пока не будет нужен может при этом отсутствовать в оперативе. Загрузку возьмет на себя механизм подкачки.

Автор: MetalFan 12.4.2011, 12:13
Вроде как BeginUpdateResource/EndUpdateResource позволяют менять ресурсы для НЕЗАПУЩЕННОГО исполнительного файла или dll.
Так что можно реализовать следующий вариант:
1. Необходимо заменить некий ресурс в работающем exe.
2. запускаем вспомогательное приложение, которому передаем необходимую информацию (какой ресурс на что менять, к примеру), закрываемся.
3. Вспомогательное приложение апдейтит/заменяет языковой ресурс в исходном файле (с пом.упомянутых функций) и запускает исходное приложение.

Автор: Gwire 12.4.2011, 12:55
Цитата(bems @  12.4.2011,  03:55 Найти цитируемый пост)
сделать файлы переводов ресурсными дллками

Я уже думал над этим вариантом... Если нет механизма добавления новых ресурсов в процессе работы - то он самый приемлемый. 
Хотя я нашел 3 функции: BeginUpdateResource, UpdateResource и EndUpdateResource. Вроде в MSDN-е описано все врозумительно,
и на значение всех параметров понятно. =( но не срабатывает.

PS: Буду пока делать с dll-ками.


Добавлено через 7 минут и 6 секунд
MetalFan, прошу прощения, почему то не увидел твоего сообщения.
Теперь, после про чтения, становится ясно, что я не правильно делал. 
Я BeginUpdateResource указывал имя файла с языком, а не .exe-файл.

Автор: MetalFan 12.4.2011, 13:03
Цитата(Gwire @  12.4.2011,  12:55 Найти цитируемый пост)
но не срабатывает.

Я в свое время вполне удачно этими функциями пользовался. Все прекрасно работало.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)