![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
||||
|
||||
|
Всем привет!
Ситуация такая. Объявил я процедуры таким образом: Код:
procedure LoadSkin(lpszPath: String; lpszIniFileName: String); stdcall; external 'isskin.dll'; // Importing UnloadSkin API from ISSkin.DLL procedure UnloadSkin(); stdcall; external 'isskin.dll'; В ресурсах программы прячу dll - библиотеку. При создании формы она должна распаковываться в ТЕМП, ну а потом начинаю работать с библиотекой.. Вообщем проблема в том, что при запуски программы я получаю ошибку, что библиотека не найдена... если ее положить конечно в папку с программой тогда работает... что можно сделать? |
|
#2
|
|||
|
|||
|
Загружать ее динамически через LoadLibrary. Статическая линковка так работать не будет - библиотека в таком случае должна быть доступна на момент загрузки приложения, т.к. при статической линковке за загрузку всех требуемых библиотек отвечает операционная система.
|
| Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
Alloc (02.06.2015)
| ||
|
#3
|
||||
|
||||
|
Да, только LoadLibrary, GetProcAddress и прочие танцы с бубном. Для особо упоротых существует код для ручной загрузки библиотеки прямо из оперативки, без сохранения на диск. Но лучше подобной фигнёй не заниматься - это плохая практика: во-первых, это неудобно, а во-вторых, передать программу в виде установщика/архива ничуть не сложнее, и при этом по системе не будут разбрасываться всякие сомнительные исполняемые файлы и загаживать место.
Последний раз редактировалось Bargest, 02.06.2015 в 12:45. |
| Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
Alloc (02.06.2015)
| ||
|
#4
|
||||
|
||||
|
Спасибо за ответы. Если не сложно, не могли бы вы предоставить небольшой пример как это происходит, для реализации поставленной задачи?
Т.е. библиотеку все равно придется распаковать и загрузить в память при помощи LoadLibrary(LibFileName: PChar)... может можно как то напрямую из ресурсов ее загрузить...? я немного не понимаю, объясните пожалуйста |
|
#5
|
||||
|
||||
|
В LoadLibrary передается путь к библиотеке. Она возвращает описатель загруженной библиотеки (насколько я помню, это обычный указатель на ее начало в памяти). Потом через GetProcAddress с использованием этого указателя нужно найти все требуемые функции из DLL и сохранить в переменных типа "функция". Затем вызывать. Это неудобно, но работает.
Грузить прямо из памяти - это извращение, потому что это делается вручную. Код, который я видел - это фактически люди сами писали свой LoadLibrary и GetProcAddress. Сами анализируют таблицы импорта и экспорта библиотеки, применяют релокации и т.д. Самый лучший выход - не заниматься всей этой фигнёй. Просто положить библиотеку рядом и всё. Если передаешь программу кому-то - собери в ZIP или в установщик и передавай его. |
| Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
Alloc (02.06.2015)
| ||
|
#6
|
||||
|
||||
|
Скажите, вот допустим есть код:
Код:
procedure TForm1.btn1Click(Sender: TObject);
type
TLoadSkin = procedure(lpszPath: String; lpszIniFileName: String);
var
DLLInstance : THandle;
LoadSkin : TLoadSkin;
begin
DLLInstance := LoadLibrary('ISSkin.dll');
if DLLInstance = 0 then
begin
MessageDlg('Невозможно загрузить DLL', mtError, [mbOK], 0);
Exit;
end;
@LoadSkin := GetProcAddress(DLLInstance, 'LoadSkin');
if @LoadSkin = nil then
LoadSkin('Skin.cjstyles','')
else
MessageDlg('Не найдена искомая процедура.', mtError, [mbOK], 0);
FreeLibrary(DLLInstance);
end;выходит сообщение "Не найдена искомая процедура." пожалуйста подскажите, что не так в коде? Заранее спасибо. |
|
#7
|
|||
|
|||
|
А LoadSkin сам писал или ктото другой?
На чём написана? Если на C/C++ то какой у неё LoadSkin.h Если на Дельфи, то покажи, как экспортирубтся функции? Или, используя TDump, покажи, какие функции экспортирует библиотека. |
| Этот пользователь сказал Спасибо icWasya за это полезное сообщение: | ||
Alloc (02.06.2015)
| ||
|
#8
|
||||
|
||||
|
Цитата:
нет, я не автор. Вообще библиотека предназначена для известного инсталлятора Inno Setup в котором используется скриптовый язык точь-в-точь как Delphi. Библиотека просто устанавливает Скин приложению. Для лучшего понимания я немного расскажу как оно работает.. В сам скрипт, в секцию [Files] добавляют два файла, саму библиотеку и скин. Код:
[Files]
; Add the ISSkin DLL used for skinning Inno Setup installations.
Source: ISSkin.dll; DestDir: {app}; Flags: dontcopy
; Add the Visual Style resource contains resources used for skinning,
; you can also use Microsoft Visual Styles (*.msstyles) resources.
Source: Office2007.cjstyles; DestDir: {tmp}; Flags: dontcopyхранится все это в екзешнике инсталлятора имеет следующие функции: Код:
[Code_] // Importing LoadSkin API from ISSkin.DLL procedure LoadSkin(lpszPath: String; lpszIniFileName: String); external 'LoadSkin@files:isskin.dll stdcall'; // Importing UnloadSkin API from ISSkin.DLL procedure UnloadSkin(); external 'UnloadSkin@files:isskin.dll stdcall'; вызывается при создании формы и при закрытии Код:
function InitializeSetup(): Boolean;
begin
ExtractTemporaryFile('Office2007.cjstyles');
LoadSkin(ExpandConstant('{tmp}\Office2007.cjstyles'), '');
Result := True;
end;
procedure DeinitializeSetup();
begin
// Hide Window before unloading skin so user does not get
// a glimpse of an unskinned window before it is closed.
ShowWindow(StrToInt(ExpandConstant('{wizardhwnd}')), 0);
UnloadSkin();
end;Инсталлятор при старте выгружает библиотеку и скин в ТЕМП после чего видимо подключает ее и устанавливает скин... вот и я этого добиваюсь. Пока что получилось только загружать скин при запуске программы и выгружать при закрытии. При условии, что dll-библиотека лежит в папке с программой ..Проще говоря, пытаюсь сделать следующее: 1.Dll - библиотека должна хранится в ресурсах программы вместе со Скином. 2.При запуске - распаковывать или загружать в память dll - библиотеку... в силу своего небольшого опыта в программировании я не знаю как лучше сделать... 3.Загружать Скин используя функцию из библиотеки 4.Выгружать из памяти\удалять при закрытии формы. Я буду очень благодарен если поможете мне осуществить задуманное, ведь очень удобно иметь возможность в любое время сменить внешний вид программы. Последний раз редактировалось Alloc, 02.06.2015 в 15:12. |
|
#9
|
|||
|
|||
|
Да просто очепятка там в коде. Как раз в случае успешного нахождения функции показывается сообщ. об ошибке.
Твой код: Код:
@LoadSkin := GetProcAddress(DLLInstance, 'LoadSkin');
if @LoadSkin = nil then
LoadSkin('Skin.cjstyles','')
else
MessageDlg('Не найдена искомая процедура.', mtError, [mbOK], 0);
FreeLibrary(DLLInstance);Надо: Код:
@LoadSkin := GetProcAddress(DLLInstance, 'LoadSkin');
if @LoadSkin = nil then
MessageDlg('Не найдена искомая процедура.', mtError, [mbOK], 0)
else
LoadSkin('Skin.cjstyles','');
FreeLibrary(DLLInstance);PS. Ну или оператор сравнения в if поменять. |
| Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
Alloc (02.06.2015)
| ||
|
#10
|
||||
|
||||
|
спасибо. странно, но если я ставлю в событие FormCreate то скин почему то не загружается... а вот если поставить код в сам Project.dpr до инициализации приложения тогда срабатывает.. но после закрытия приложения вылетает куча ошибок со ссылкой на разные библиотеки...
|
|
#11
|
|||
|
|||
|
Это надо отдельно разбираться.
Видимо, скин должен быть загружен на момент инициализации приложения (возможно, хакают создание форм; дело в том, что в момент OnCreate, само окно уже создано). По поводу ошибок с ссылками на разные библиотеки - надо смотреть что за ошибки и откуда ноги растут. Ну и проверить запуск не из IDE, может просто там действительно куча разных исключений, но они отлавливаются внутри кода и наружу не выходят. |
| Этот пользователь сказал Спасибо lmikle за это полезное сообщение: | ||
Alloc (02.06.2015)
| ||
|
#12
|
||||
|
||||
|
Слишком все это сложно оказалось)) В любом случае большое спасибо lmikle за помощь и всем остальным тоже огромное спасибо! Пойду тогда по другому пути.. жаль, вроде бы такая мелочь - а столько геморроя))
|
|
#13
|
||||
|
||||
|
Скажите, а как вы смотрите на то, чтобы написать отдельно программу которая будет распаковывать в ТЕМП основную программу с библиотекой и скином и запускать ее оттуда? Потом удалять все это естественно... и так каждый раз. на сколько это разумно?) Так делают?
заранее спасибо |
|
#14
|
||||
|
||||
|
*хлебный троллейбус.жпг*
Делают. Тот же винрар позволяет распаковать во временнуюипапку и запустить оттуда программу. Потом всё потрёт. SFX-архив. |
| Этот пользователь сказал Спасибо M.A.D.M.A.N. за это полезное сообщение: | ||
Alloc (03.06.2015)
| ||
|
#15
|
||||
|
||||
|
Благодарю)
|