![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Есть образец программки, делающей tracert. Я хочу получить то же самое, но без формы, т.е. чтобы была процедура с входными параметрами - хост, хопы и Tstrings какой-нибудь - и ее можно было запускать из других проектов, просто подключая этот юнит. Подскажите плз, как "превратить" эту программку в юнит.
|
|
#2
|
|||
|
|||
|
Вся работа собрана здесь: procedure TTraceThread.Execute;
фактически, тебе надо просто запускать этот поток и ждать, пока он закончит работу. Ну и вывод заместо Memo переписать в TStringList (тоже метот того же потока). |
|
#3
|
|||
|
|||
|
Но ведь мне надо к этой процедуре приделать входные параметры. А в проге они объявлены глобально... Мне кажется, что придется к каждой процедуре (Баттонклик наверно, ведь с него все начинается; собсно thread.execute; и TTraceThread.Log). Я пытался для начала только вывод переделать, чтобы передавались строки в произвольный TStrings, его к Логу приписал (Только в нем в мемо выводится), а после этого делфи стала ругаться на Synchronize(Log), пробовал писать типа так Synchronize(Log(Combobox1.items)); - все равно ругается...
|
|
#4
|
|||
|
|||
|
Ага, сделай переменную внутри класса и вывод лога будет писать в нее. Для Synchronize нужно, что бы метод был без параметров... сам с этим намучался... приходится делать через переменные (поля) класса потока. Кстати, если это будет переменная класса, и она не будет читаться/писаться во время работы потока, то можно Synchronize и не использовать.
|
|
#5
|
|||
|
|||
|
Вроде получилось, за одним исключением - как понять, когда трассировка завершена? Т.е. я сделал некую процедуру, которую буду вызывать из основной программы: ей на вход подаются адрес хоста, число хопов и переменная, куда должен попасть результат трассировки.
Код:
procedure tracerout(const adr:string;hop:integer; var otvet:string);
begin
otvet:='';
with TTraceThread.Create(False) do
begin
FreeOnTerminate := True;
DestinationAddress := adr;
IterationCount := hop;
Resume;
end;
{res - переменная, в которую Log заталкивает ответ}
{??? otvet:=res; ???}
end; |
|
#6
|
|||
|
|||
|
Забил на это дело, код трасерта скопипастил в прогу, вроде в целом ничего получилось))) Но - почему не посылаются эхо-запросы?
Код:
Error := IcmpSendEcho(TraceHandle,
DestAddr.S_addr,
nil,
0,
@IP,
ECHO,
SizeOf(ICMP_ECHO),
5000);З.Ы. Наверно важно - я пишу не обычное приложение, а дллка-плагин для ИЕ. |
|
#7
|
|||
|
|||
|
Во первых, показывай весь код.
Возможно, просто что-то не инициализированно и поэтому не работает. |
|
#8
|
|||
|
|||
|
Да вроде все скопировал, ничего не упустил.
Код в аттаче, весь плагин. Открывать ProxyBand.dpr, смотреть на Button2.Click и далее, TTraceThread.Trace и др. |
|
#9
|
|||
|
|||
|
Короче:
Код:
unit TraceRt;
interface
// ===========================================================================
// TRACEROUTE Class
// Mike Heydon Dec 2003
//
// Method
// Trace(IpAddress : string; ResultList : TStrings)
// Returns semi-colon delimited list of ip routes to target
// format .. IP ADDRESS; PING TIME MS; TIME TO LIVE; STATUS
//
// Properties
// IcmpTimeOut : integer (Default = 5000ms)
// IcmpMaxHops : integer (Default = 40)
// ===========================================================================
uses Forms, Windows, Classes, SysUtils, IdIcmpClient;
type
TTraceRoute = class(TObject)
protected
procedure ProcessResponse(Status : TReplyStatus);
procedure AddRoute(AResponseTime : DWORD;
AStatus: TReplyStatus; const AInfo: string );
private
FIcmpTimeOut,
FIcmpMaxHops : integer;
FResults : TStringList;
FICMP : TIdIcmpClient;
FPingStart : cardinal;
FCurrentTTL : integer;
procedure PingTarget;
public
constructor Create;
procedure Trace(const AIpAddress : string; AResultList : TStrings);
property IcmpTimeOut : integer read FIcmpTimeOut write FIcmpTimeOut;
property IcmpMaxHops : integer read FIcmpMaxHops write FIcmpMaxHops;
end;
// ---------------------------------------------------------------------------
implementation
// ========================================
// Create the class and set defaults
// ========================================
constructor TTraceRoute.Create;
begin
IcmpTimeOut := 5000;
IcmpMaxHops := 40;
end;
// =============================================
// Use Indy component to ping hops to target
// =============================================
procedure TTraceRoute.PingTarget;
var wOldMode : DWORD;
begin
Application.ProcessMessages;
inc(FCurrentTTL);
if FCurrentTTL < FIcmpMaxHops then begin
FICMP.TTL := FCurrentTTL;
FICMP.ReceiveTimeout := FIcmpTimeOut;
FPingStart := GetTickCount;
wOldMode := SetErrorMode(SEM_FAILCRITICALERRORS);
try
FICMP.Ping;
ProcessResponse(FICMP.ReplyStatus);
except
FResults.Add('0.0.0.0;0;0;ERROR');
end;
SetErrorMode(wOldMode);
end
else
FResults.Add('0.0.0.0;0;0;MAX HOPS EXCEEDED');
end;
// ============================================================
// Add the ping reply status data to the returned stringlist
// ============================================================
procedure TTraceRoute.AddRoute(AResponseTime : DWORD;
AStatus: TReplyStatus;
const AInfo: string );
begin
FResults.Add(AStatus.FromIPAddress + ';' +
IntToStr(GetTickCount - AResponseTime) + ';' +
IntToStr(AStatus.TimeToLive) + ';' + AInfo);
end;
// ============================================================
// Process the ping reply status record and add to stringlist
// ============================================================
procedure TTraceRoute.ProcessResponse(Status : TReplyStatus);
begin
case Status.ReplyStatusType of
// Last Leg - Terminate Trace
rsECHO : AddRoute(FPingStart,Status,'OK');
// More Hops to go - Continue Pinging
rsErrorTTLExceeded : begin
AddRoute(FPingStart,Status,'OK');
PingTarget;
end;
// Error conditions - Terminate Trace
rsTimeOut : AddRoute(FPingStart,Status,'TIMEOUT');
rsErrorUnreachable : AddRoute(FPingStart,Status,'UNREACHABLE');
rsError : AddRoute(FPingStart,Status,'ERROR');
end;
end;
// ======================================================
// Trace route to target IP address
// Results returned in semi-colon delimited stringlist
// IP; TIME MS; TIME TO LIVE; STATUS
// ======================================================
procedure TTraceRoute.Trace(const AIpAddress : string;
AResultList : TStrings);
begin
FICMP := TIdIcmpClient.Create(nil);
FICMP.Host := AIpAddress;
FResults := TStringList(AResultList);
FResults.Clear;
FCurrentTTL := 0;
PingTarget;
FICMP.Free;
end;
{eof}
end.Google рулит!!! |
|
#10
|
|||
|
|||
|
Это я видел, сейчас еще раз проверил - "Access violation bla-bla-bla in Proxyband.dll"
|
|
#11
|
|||
|
|||
|
Уфф, ну и жестоко все это было, но, оказывается, все просто))))
• У меня не получилось сделать вывод трасерта в переменную так, чтобы основное приложение могло узнать, когда считывать. Поэтому сделал вывод трасерта в произвольный файл - основная прога все равно не узнает, когда смотреть, но для моей цели это не критично. Да и, в конце концов, можно регулярно проверять папку на наличие файла. • Не бейте меня сильно за, наверное, не лучшую реализацию вывода в файл • Всегда меня просто добивает то, что люди юнит-то выложат, а вот пример использования - нет. И сиди, думай, как же его вызвать. Поэтому используется примерно так (Если добавлять tracert.pas к проекту) Код:
with tracert.TTraceThread.Create(false) do
begin
FreeOnTerminate := True;
FileName:='Здесь путь к файлу';
DestinationAddress := 'Здесь айпи или хост, без протокола'; //Т.е. 'ya.ru' - верно, 'http://ya.ru' - нет.
IterationCount := 6; //Здесь количество прыжков
Resume;
end;Последний раз редактировалось lega4, 07.10.2010 в 19:22. |