Форум: "WinAPI";
Текущий архив: 2006.01.01;
Скачать: [xml.tar.bz2];
ВнизКак получить адрес процедур собственной программы (по названию п) Найти похожие ветки
← →
AllDontFire (2005-10-29 15:24) [0]Пробовал
GetProcAddress
, но, насколько я понял, так нельзя, это только для Dll?
← →
begin...end © (2005-10-29 15:48) [1]> AllDontFire (29.10.05 15:24)
Это возможно и для EXE, но нужные подпрограммы нужно включить в список exports.
← →
wp2 (2005-10-29 15:52) [2]А если попробовать @
← →
raiks (2005-10-29 19:05) [3]procedure DoSomething;
begin
end;
var p: Pointer;
begin
p:=@DoSomething;
ShowMessage("Адрес DoSomething: " + IntToStr(Cardinal(p)));
end;
← →
AllDontFire (2005-10-29 22:15) [4]raiks,
p:=@DoSomething - -это понятно.
Но мне нужно найти адрес, передавая символьное название процедуры как в
GetProcAddress.
← →
wp2 (2005-10-30 01:39) [5]Удалено модератором
← →
raiks (2005-10-30 02:29) [6]Объясните конкретнее, для чего вам это нужно. Почему нельзя использовать приведенный пример?
← →
Джо © (2005-10-30 02:37) [7]
> [4] AllDontFire (29.10.05 22:15)
Разумумный ответ см. [1] begin...end © (29.10.05 15:48)
Другой подход - сделать процуры published-методами какого-нибудь класса, скомпилированным с директовой {$M+}. Тогда можно искать методы по имени.
Непонятно только, зачем это нужно? Может, если объяснить конкретную задачу, найдется более оптимальное решение.
← →
Джо © (2005-10-30 02:01) [8]Делать мне, наверное, нечего.
В общем, вот иллюстрация обоих подходов, два консольных приложения, в качестве параметра коммандной строки принимающих имя процедуры, которую необходимо выполнить.
---
Подход с получением адреса экспортируемой функции.
program Project2;
{$APPTYPE CONSOLE}
uses
Windows,
SysUtils;
// эта процедура экспортируется
procedure DoSomething;
begin
WriteLn ("DoSomething called.");
end;
// эта процедура экспортируется
procedure DoSomethingElse;
begin
WriteLn ("DoSomethingElse called.");
end;
// а эта процедура НЕ экспортируется
procedure YouCannotCallMe;
begin
WriteLn ("You should not see this message.");
end;
// экспортируем нужные функции
exports
DoSomething,
DoSomethingElse;
var
ProcName: string;
Proc: procedure;
begin
ProcName := ParamStr(1);
if ProcName = "" then
begin
WriteLn ("Specify a procedure name");
Exit;
end;
proc := GetProcAddress(0,PChar(ProcName));
if Assigned(Proc) then
Proc()
else
WriteLn ("Procedure ",ProcName," not found in executable.");
ReadLn;
end.
---
Подход с получением адреса published-метода класса.
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils,
TypInfo;
type
TCommander = class
public
procedure YouCannotCallMe;
published
procedure DoSomething;
procedure DoSomethingElse;
end;
{ TCommander }
procedure TCommander.DoSomethingElse;
begin
WriteLn ("DoSomethingElse called.");
end;
procedure TCommander.DoSomething;
begin
WriteLn ("DoSomething called.");
end;
procedure TCommander.YouCannotCallMe;
begin
WriteLn ("You should not see this message.");
end;
var
ProcName: string;
Proc: procedure;
Commander: TCommander;
begin
ProcName := ParamStr(1);
if ProcName = "" then
begin
WriteLn ("Specify a procedure name");
Exit;
end;
Commander := TCommander.Create;
try
Proc := Commander.MethodAddress (ProcName);
if Assigned (Proc) then
Proc ()
else
WriteLn ("Unknown command requested.");
finally
Commander.Free;
end;
ReadLn;
end.
П.С. Надеюсь, пригодится.
И -- я наврал насчет директивы {$M+}, сейчас вожусь с RTTI и немного заработался, видимо :(
← →
Джо © (2005-10-30 02:34) [9]Мда... спешка к добру не приводит. Исправления во второй пример, позорные:
var
...
Proc: procedure of object;
...
TMethod(Proc).Code := Commander.MethodAddress (ProcName);
TMethod(Proc).Data := Commander;
← →
AllDontFire (2005-10-30 11:23) [10]Спасибо, всё понятно.
Ну это нужно, например, когда, в зависимости от какого-либо входного параметра, необходимо запустить опр. процедуру. Можно конечно выйти из положения черезIF
, но, а если много вариантов входных параметров, то и "Ифов" будет много, а это не удобно я думаю.
← →
raiks (2005-10-30 13:39) [11]Джо
Ради интереса опробовал 1-й ваш пример. Работает :) Потом решил проделать то же самое с другим *.exe, в раздел exports которого добавлена соответствующая строка. Файл нормально загрузился с помощью LoadLibrary, адрес процедуры DoSomething тоже нашелся, но при попытке вызвать ее вылезло неизбывное сообщение об Access Violation. Я так понимаю, это связано с атрибутами доступа к памяти? Можно ли это исправить?
-----------Project1.exe------------
program Project1;
uses Windows;
procedure DoSomething;
begin
MessageBox(0, "Hello from DoSomething()", nil, MB_ICONWARNING);
end;
exports
DoSomething;
begin
end.
-----------Project2.exe------------
var
hLib: THandle;
DoSmth: procedure;
begin
hLib:=LoadLibrary("f:\project1.exe");
if hLib<>0 then
begin
MessageBox(0, "Module Project1 was loaded!", nil, MB_ICONWARNING);
@DoSmth:=GetProcAddress(hLib, "DoSomething");
if @DoSmth<>nil then
begin
MessageBox(0, "Procedure DoSomething() was found!", nil, MB_ICONWARNING);
DoSmth;
end;
FreeLibrary(hLib);
end;
end;
← →
Digitman © (2005-10-31 10:17) [12]
> raiks (30.10.05 13:39) [11]
> связано с атрибутами доступа к памяти?
нет, это связано с совершенно иным - с обработкой загрузчиком таблицы релокации и инициализацией pe-модуля
← →
Polevi © (2005-10-31 10:47) [13]можно сделать через FindClass
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2006.01.01;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.009 c