Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Система";
Текущий архив: 2004.05.16;
Скачать: [xml.tar.bz2];

Вниз

Импорт функции из .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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.48 MB
Время: 0.034 c
3-1082634420
Frozzen
2004-04-22 15:47
2004.05.16
Позиция курсора в DBGrid


1-1083157764
killer
2004-04-28 17:09
2004.05.16
Сортировка в StringGrid


14-1082892916
Dimedrol
2004-04-25 15:35
2004.05.16
Хочу украсить прогу... :-)


1-1083321384
Vitaliy
2004-04-30 14:36
2004.05.16
Кто работал с компонентом PrintPreview?


7-1080573409
TankMan
2004-03-29 19:16
2004.05.16
Как узнать высоту заголовка окон?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский