Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.16;
Скачать: CL | DM;

Вниз

Импорт функции из .exe   Найти похожие ветки 

 
Fiend ©   (2004-03-31 15:25) [0]

Здравствуйте Уважаемые!!!

Есть у меня с коллегой общий проект. В нём есть утилита для автоматического обновления. Естественно .exe файл.

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

Функцию сделал, но вот незадача, как только exe загружен LoadLibrary и указатель на ф-цию получен от GetProcAddress, мы ее ессесно вызываем и в отладчике замечаем ужасную картину: на первой же команде происходит AV. Где порыть ума не приложу.

это экспортируемое:
type
 TScript = record
           Size: WORD;
           PScript: PChar;
           end;
 PScript = ^TScript;

function ExternalCall(Script: PScript): boolean; stdcall;
begin
 MainForm:= TMainForm.Create(Application);
 MainForm.UpdateNow(Script);
 MainForm.ShowModal;
 Result:= MainForm.LoadResult=1;
 MainForm.Free;
end;

exports ExternalCall;

а это уже загрузка и выполнение:
type
 TExternalCall = function (Script: PScript): boolean; stdcall;

var hLibrary: THandle;
   fExternalCall: TExternalCall;
   Script: TScript;
   Result: boolean;
begin
 hLibrary:= LoadLibrary("UpdWizard.exe");
 @fExternalCall:= GetProcAddress(hLibrary, "ExternalCall");
 Script.PScript:= AllocMem(1000);
 StrPCopy(Script.PScript, "/ok/cgi/news.exe?getupdscr&stylea");
 Script.Size:= StrLen(Script.PScript);
 Result:= fExternalCall(@Script);
 FreeLibrary(hLibrary);
 FreeMem(Script.PScript, 1000);
end.

Помогите пожалуйста, хотя бы обсуждением.


 
Cobalt ©   (2004-03-31 15:47) [1]

ГЫЫЫЫ :))))
А Application кто будет инициализировать????
Это же объект - в ЕХЕ-ке загруженном, а не в вашем, вызывающем.

Общая рекомендация - отделяйте "бизнес-логику" (деловую логику) от интерфейса!!!


 
Fiend ©   (2004-03-31 15:53) [2]

Я бы не стал так смеяться.
Потому что даже если первой коммандой поставить тривиальнейший Beep(), то всё равно ошибка прямо на нём. Да и в конце концов можно создавать форму указывая nil.

Так что дело не в этом.


 
Digitman ©   (2004-03-31 16:14) [3]


> Fiend


не смотря на ржание Cobalt"а аки жеребца молодого, он прав
прав в том, что загрузка и/или инициализация требуемых модулей (в т.ч. и в 1-ю очередь - VCL-модулей) происходит при передаче системой управления на точку входа в exe .. что не происходит при LoadLibrary()


 
Fiend ©   (2004-03-31 16:18) [4]

Что вы предлагаете сделать?
Application.Initialize первой же строкой?
Делал, результат тот же.


 
Digitman ©   (2004-03-31 16:22) [5]

попробуй-ка реализовать и экспортировать в exe простую ф-цию

const SomeStr: PChar = "Hello, World !";
function GetSomeString: PChar;
begin
Result := SomeStr;
end;

и вызвать эту ф-цию после LoadLibrary() и GetProcAddress()

ShowMessage(String(GetSomeString));

и все пройдет на ура !

почему ? да потому что тело импортируемой ф-ции не содержит ни единого обращения ни к одному из внешних и/или неявно инициализируемых (в ходе старта exe-процесса) модулей, т.е. никак не зависит от какого-либо дополнительного/вспомогательного кода/данных ... иными словами - импортируемая ф-ция реализована в теле exe-модуля как 100%-но самодостаточная


 
Digitman ©   (2004-03-31 16:26) [6]


> Fiend


предлагаю не заморачиваться этой идеей, если она хоть как-то использует внутри экспортируемой ф-ции VCL

все, что тебе нужно, вполне реализуемо и иными способами, и манипуляция с ком.строкой - не самый худший способ ... просто продумать следует его


 
Digitman ©   (2004-03-31 16:28) [7]


> Application.Initialize первой же строкой?
> Делал, результат тот же.


а кто и когда создал объект Application ?

никто и никогда !

вот тебе и ответ


 
Fiend ©   (2004-03-31 16:32) [8]

Урезал функции до предела
это экспортируем
function ExternalCall{(Script: PScript)}: boolean; stdcall;
begin
ShowMessage("asdasdf");
{  assert(Application=nil, "sux");
 MainForm:= TMainForm.Create(nil);
 MainForm.UpdateNow(Script);
 MainForm.ShowModal;
 Result:= MainForm.LoadResult=1;
 MainForm.Free;}
end;

это импортируем
type
 TExternalCall = function {(Script: PScript)}: boolean; stdcall;
Загружаем, получаем адрес, и вызываем:
AV.

Вы меня кажется недопоняли, или невнимательно прочли:
АВ падает сразу на первой команде, даже если это assert или beep

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


 
Fiend ©   (2004-03-31 16:55) [9]

Следующим шагом, чтобы проверить слова Digitman`a отключил из экспортирующего ехе всё, и оставил только одну экспортируемую функцию в которой стоит assert
и всё равно АВ не пропал. следовательно, т.к. ничто из VCL не подключено и нет никаких там инициализаций, то дело не в ней.
Но вот в чём непонятно


 
Digitman ©   (2004-03-31 16:56) [10]


> даже если это assert или beep


assert() использует многие данные из модуля system.pas, раздел initialization которого никто не вызывал

beep() использует библ-ку user32.dll, точка входа в ф-цию MessageBeep которой, возможно, формируется динамически в ходе иниц-ции заинтересованных модулей ехе в ходе его нормальной работы

ShowMessage("asdasdf") использует модуль Forms, который тоже никто не инициализировал, равно как никто не создавал объект Application, интенсивно используемый этим модулем при манипуляциях с формами

кр.того, ехе м.б. собран с пакетами времени выполнения. которые тоже никто не грузил и не инициализировал


 
Digitman ©   (2004-03-31 16:59) [11]


> отключил из экспортирующего ехе всё


прелюбопытно, что конкретно ... и каким конкретно образом ...

что, код/данные, принадлежащие System.pas, тоже умудрился отключить ?


 
Fiend ©   (2004-03-31 17:07) [12]

То Digitman ©   (31.03.04 16:59) [11]
ну да его ессесно не отключишь. про это я забыл.

Я уже "слегка" запутался: какой вариант ты предлагаешь?
1) переделать всё же в ДЛЛ и ее грузить.
2) использвать командную строку.
3) или может что то еще...


 
Digitman ©   (2004-03-31 17:14) [13]

если два или более приложений желают использовать один и тот же код , есть прямой смысл вынести алгоритм "утилиты обновления" в DLL, и пусть все заинтересованные приложения обращаются к этой ДЛЛ для запуска этого алгоритма ... самый разумный подход ... для того и существует концепция и механизм динамически линкуемых библ-к


 
Fiend ©   (2004-03-31 17:18) [14]

То Digitman ©   (31.03.04 17:14) [13]
Это всё понятно, но хотелось как всегда с минимальной затратой времени, а вылилось в полдня. Ну да ладно, за-то опыт в обасти экспорта из ехе.

ВСЕМ СПАСИБО!!!
обсуждение закрыто!



Страницы: 1 вся ветка

Текущий архив: 2004.05.16;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.025 c
1-1083319014
grover
2004-04-30 13:56
2004.05.16
как обновить экран?


11-1069673509
Fktrc
2003-11-24 14:31
2004.05.16
TKOLOpenSaveDialog - вызывается только при второй попытке


1-1082788613
Hkr
2004-04-24 10:36
2004.05.16
TThred...


6-1080227029
Pr0t0n
2004-03-25 18:03
2004.05.16
SMS b Delphi Часть Вторая.


3-1082373333
Евкисий
2004-04-19 15:15
2004.05.16
правка TQuery