如何在启动机器时自动运行adsl拨号(1)

类别:Delphi 点击:0 评论:0 推荐:

我们通常希望有一台机器能经常挂在网上,现在有了adsl包月服务,这已经不是问题。但是最近adsl总是会断线,当我回家想从公司的机器上拷贝一些文件的时候,有时会发现已经连接不上了。所以我做个程序所要实现的功能有这么两个,一是用程序来实现adsl拨号,二是要定时检测网络状态,三是要在启动机器时运行(既注册为服务)
我们先看一下如何做一个拨号程序
首先建一个ras拨号的单元文件(这是网上搜集的)
unit Ras;

interface

uses
    Windows, SysUtils;

{$DEFINE WINVER400}
const
    RasUnitVersion        = 110;
    CopyRight    : String = ' RasUnit (c) 97-98 F. Piette V1.10 ';
    rasapi32              = 'rasapi32.dll';

    UNLEN                 = 256;    // Maximum user name length
    PWLEN                 = 256;    // Maximum password length
    CNLEN                 = 15;     // Computer name length
    DNLEN                 = CNLEN;  // Maximum domain name length

    RAS_MaxDeviceType     = 16;
    RAS_MaxPhoneNumber    = 128;
    RAS_MaxIpAddress      = 15;
    RAS_MaxIpxAddress     = 21;

{$IFDEF WINVER400}
    RAS_MaxEntryName      = 256;
    RAS_MaxDeviceName     = 128;
    RAS_MaxCallbackNumber = RAS_MaxPhoneNumber;
{$ELSE}
    RAS_MaxEntryName      = 20;
    RAS_MaxDeviceName     = 32;
    RAS_MaxCallbackNumber = 48;
{$ENDIF}

    RAS_MaxAreaCode       = 10;
    RAS_MaxPadType        = 32;
    RAS_MaxX25Address     = 200;
    RAS_MaxFacilities     = 200;
    RAS_MaxUserData       = 200;

    RASCS_OpenPort            = 0;
    RASCS_PortOpened          = 1;
    RASCS_ConnectDevice       = 2;
    RASCS_DeviceConnected     = 3;
    RASCS_AllDevicesConnected = 4;
    RASCS_Authenticate        = 5;
    RASCS_AuthNotify          = 6;
    RASCS_AuthRetry           = 7;
    RASCS_AuthCallback        = 8;
    RASCS_AuthChangePassword  = 9;
    RASCS_AuthProject         = 10;
    RASCS_AuthLinkSpeed       = 11;
    RASCS_AuthAck             = 12;
    RASCS_ReAuthenticate      = 13;
    RASCS_Authenticated       = 14;
    RASCS_PrepareForCallback  = 15;
    RASCS_WaitForModemReset   = 16;
    RASCS_WaitForCallback     = 17;
    RASCS_Projected           = 18;

{$IFDEF WINVER400}
    RASCS_StartAuthentication = 19;
    RASCS_CallbackComplete    = 20;
    RASCS_LogonNetwork        = 21;
{$ENDIF}
    RASCS_SubEntryConnected   = 22;
    RASCS_SubEntryDisconnected= 23;

    RASCS_PAUSED              = $1000;
    RASCS_Interactive         = RASCS_PAUSED;
    RASCS_RetryAuthentication = (RASCS_PAUSED + 1);
    RASCS_CallbackSetByCaller = (RASCS_PAUSED + 2);
    RASCS_PasswordExpired     = (RASCS_PAUSED + 3);

    RASCS_DONE                = $2000;
    RASCS_Connected           = RASCS_DONE;
    RASCS_Disconnected        = (RASCS_DONE + 1);

    // If using RasDial message notifications, get the notification message code
    // by passing this string to the RegisterWindowMessageA() API.
    // WM_RASDIALEVENT is used only if a unique message cannot be registered.
    RASDIALEVENT    = 'RasDialEvent';
    WM_RASDIALEVENT = $CCCD;

    // TRASPROJECTION
    RASP_Amb        = $10000;
    RASP_PppNbf     = $0803F;
    RASP_PppIpx     = $0802B;
    RASP_PppIp      = $08021;
    RASP_Slip       = $20000;

type
    THRASCONN     = THandle;
    PHRASCONN     = ^THRASCONN;
    TRASCONNSTATE = DWORD;
    PDWORD        = ^DWORD;
    PBOOL         = ^BOOL;

    TRASDIALPARAMS = packed record
        dwSize           : DWORD;
        szEntryName      : array [0..RAS_MaxEntryName] of Char;
        szPhoneNumber    : array [0..RAS_MaxPhoneNumber] of Char;
        szCallbackNumber : array [0..RAS_MaxCallbackNumber] of Char;
        szUserName       : array [0..UNLEN] of Char;
        szPassword       : array [0..PWLEN] of Char;
        szDomain         : array [0..DNLEN] of Char;
{$IFDEF WINVER401}
        dwSubEntry       : DWORD;
        dwCallbackId     : DWORD;
{$ENDIF}
        szPadding        : array [0..2] of Char;
    end;
    PRASDIALPARAMS = ^TRASDIALPARAMS;

    TRASDIALEXTENSIONS = packed record
        dwSize     : DWORD;
        dwfOptions : DWORD;
        hwndParent : HWND;
        reserved   : DWORD;
    end;
    PRASDIALEXTENSIONS = ^TRASDIALEXTENSIONS;

    TRASCONNSTATUS = packed record
        dwSize       : DWORD;
        RasConnState : TRASCONNSTATE;
        dwError      : DWORD;
        szDeviceType : array [0..RAS_MaxDeviceType] of char;
        szDeviceName : array [0..RAS_MaxDeviceName] of char;
        szPadding    : array [0..1] of Char;
    end;
    PRASCONNSTATUS = ^TRASCONNSTATUS;

    TRASCONN = packed record
        dwSize       : DWORD;
        hRasConn     : THRASCONN;
        szEntryName  : array [0..RAS_MaxEntryName] of char;
{$IFDEF WINVER400}
        szDeviceType : array [0..RAS_MaxDeviceType] of char;
        szDeviceName : array [0..RAS_MaxDeviceName] of char;
{$ENDIF}
        szPadding    : array [0..0] of Char;
    end;
    PRASCONN = ^TRASCONN;

    TRASENTRYNAME = packed record
        dwSize       : DWORD;
        szEntryName  : array [0..RAS_MaxEntryName] of char;
        szPadding    : array [0..2] of Char;
    end;
    PRASENTRYNAME = ^TRASENTRYNAME;

    TRASENTRYDLG = packed record
        dwSize       : DWORD;
        hWndOwner    : HWND;
        dwFlags      : DWORD;
        xDlg         : LongInt;
        yDlg         : LongInt;
        szEntry      : array [0..RAS_MaxEntryName] of char;
        dwError      : DWORD;
        Reserved     : DWORD;
        Reserved2    : DWORD;
        szPadding    : array [0..2] of Char;
    end;
    PRASENTRYDLG = ^TRASENTRYDLG;

    TRASPROJECTION = integer;
    TRASPPPIP = record
        dwSize  : DWORD;
        dwError : DWORD;
        szIpAddress : array [0..RAS_MaxIpAddress] of char;
    end;


function RasDialA(RasDialExtensions: PRASDIALEXTENSIONS;
                  PhoneBook     : PChar;
                  RasDialParams : PRASDIALPARAMS;
                  NotifierType  : DWORD;
                  Notifier      : Pointer;
                  RasConn       : PHRASCONN
                 ): DWORD; stdcall;
function RasGetErrorStringA(
                  uErrorValue   : DWORD; // error to get string for
                  szErrorString : PChar; // buffer to hold error string
                  cBufSize      : DWORD  // size, in characters, of buffer
                 ): DWORD; stdcall;
function RasHangupA(RasConn: THRASCONN): DWORD; stdcall;
function RasConnectionStateToString(nState : Integer) : String;
function RasGetConnectStatusA(
                  hRasConn: THRASCONN;   // handle to RAS connection of interest
                  lpRasConnStatus : PRASCONNSTATUS // buffer to receive status data
                 ): DWORD; stdcall;
function RasEnumConnectionsA(
                  pRasConn : PRASCONN;  // buffer to receive connections data
                  pCB      : PDWORD;  // size in bytes of buffer
                  pcConnections : PDWORD // number of connections written to buffer
                 ) : DWORD; stdcall
function RasEnumEntriesA(
                  Reserved : Pointer;  // reserved, must be NIL
                  szPhonebook : PChar;  // full path and filename of phonebook file
                  lpRasEntryName : PRASENTRYNAME; // buffer to receive entries
                  lpcb : PDWORD;  // size in bytes of buffer
                  lpcEntries : PDWORD  // number of entries written to buffer
                 ) : DWORD; stdcall;
function RasGetEntryDialParamsA(
                  lpszPhonebook : PChar; // pointer to the full path and filename of the phonebook file
                  lprasdialparams : PRASDIALPARAMS; // pointer to a structure that receives the connection parameters
                  lpfPassword : PBOOL    // indicates whether the user's password was retrieved
                 ) : DWORD; stdcall;
function RasEditPhonebookEntryA(
                   hWndParent : HWND;     // handle to the parent window of the dialog box
                   lpszPhonebook : PChar; // pointer to the full path and filename of the phonebook file
                   lpszEntryName : PChar  // pointer to the phonebook entry name
                 ) : DWORD; stdcall;
//function RasEntryDlgA(
//                   lpszPhonebook : PChar; // pointer to the full path and filename of the phone-book file
//                   lpszEntry : PChar;     // pointer to the name of the phone-book entry to edit, copy, or create
//                   lpInfo : PRASENTRYDLG  // pointer to a structure that contains additional parameters
//                 ) : DWORD; stdcall;
function RasCreatePhonebookEntryA(
                     hWndParent : HWND;    // handle to the parent window of the dialog box
                     lpszPhonebook : PChar // pointer to the full path and filename of the phonebook file
                   ) : DWORD; stdcall;

function RasGetProjectionInfoA(
                    hRasConn      : THRASCONN;      // handle that specifies remote access connection of interest
                    RasProjection : TRASPROJECTION; // specifies type of projection information to obtain
                    lpProjection  : Pointer;        // points to buffer that receives projection information
                    lpcb          : PDWORD          // points to variable that specifies buffer size
                   ) : DWORD; stdcall;
function RasGetIPAddress: string;

implementation


{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function RasConnectionStateToString(nState : Integer) : String;
begin
    case nState of
    RASCS_OpenPort:             Result := 'Opening Port';
    RASCS_PortOpened:           Result := 'Port Opened';
    RASCS_ConnectDevice:        Result := 'Connecting Device';
    RASCS_DeviceConnected:      Result := 'Device Connected';
    RASCS_AllDevicesConnected:  Result := 'All Devices Connected';
    RASCS_Authenticate:         Result := 'Starting Authentication';
    RASCS_AuthNotify:           Result := 'Authentication Notify';
    RASCS_AuthRetry:            Result := 'Authentication Retry';
    RASCS_AuthCallback:         Result := 'Callback Requested';
    RASCS_AuthChangePassword:   Result := 'Change Password Requested';
    RASCS_AuthProject:          Result := 'Projection Phase Started';
    RASCS_AuthLinkSpeed:        Result := 'Link Speed Calculation';
    RASCS_AuthAck:              Result := 'Authentication Acknowledged';
    RASCS_ReAuthenticate:       Result := 'Reauthentication Started';
    RASCS_Authenticated:        Result := 'Authenticated';
    RASCS_PrepareForCallback:   Result := 'Preparation For Callback';
    RASCS_WaitForModemReset:    Result := 'Waiting For Modem Reset';
    RASCS_WaitForCallback:      Result := 'Waiting For Callback';
    RASCS_Projected:            Result := 'Projected';
{$IFDEF WINVER400}
    RASCS_StartAuthentication:  Result := 'Start Authentication';
    RASCS_CallbackComplete:     Result := 'Callback Complete';
    RASCS_LogonNetwork:         Result := 'Logon Network';
{$ENDIF}
    RASCS_SubEntryConnected:    Result := '';
    RASCS_SubEntryDisconnected: Result := '';
    RASCS_Interactive:          Result := 'Interactive';
    RASCS_RetryAuthentication:  Result := 'Retry Authentication';
    RASCS_CallbackSetByCaller:  Result := 'Callback Set By Caller';
    RASCS_PasswordExpired:      Result := 'Password Expired';
    RASCS_Connected:            Result := 'Connected';
    RASCS_Disconnected:         Result := 'Disconnected';
    else
        Result := 'Connection state #' + IntToStr(nState);
    end;
end;


{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function RasGetIPAddress: string;
var
    RASConns   : TRasConn;
    dwSize     : DWORD;
    dwCount    : DWORD;
    RASpppIP   : TRASPPPIP;
begin
    Result          := '';
    RASConns.dwSize := SizeOf(TRASConn);
    RASpppIP.dwSize := SizeOf(RASpppIP);
    dwSize          := SizeOf(RASConns);
    if RASEnumConnectionsA(@RASConns, @dwSize, @dwCount) = 0 then begin
        if dwCount > 0 then begin
            dwSize := SizeOf(RASpppIP);
            RASpppIP.dwSize := SizeOf(RASpppIP);
            if RASGetProjectionInfoA(RASConns.hRasConn,
                                     RASP_PppIp,
                                     @RasPPPIP,
                                     @dwSize) = 0 then
                Result := StrPas(RASpppIP.szIPAddress);
       end;
    end;
end;

 

{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function RasDialA; external rasapi32 name 'RasDialA';
function RasGetErrorStringA; external rasapi32 name 'RasGetErrorStringA';
function RasHangUpA; external rasapi32 name 'RasHangUpA';
function RasGetConnectStatusA; external rasapi32 name 'RasGetConnectStatusA';
function RasEnumConnectionsA; external rasapi32 name 'RasEnumConnectionsA';
function RasEnumEntriesA; external rasapi32 name 'RasEnumEntriesA';
function RasGetEntryDialParamsA; external rasapi32 name 'RasGetEntryDialParamsA';
function RasEditPhonebookEntryA; external rasapi32 name 'RasEditPhonebookEntryA';
//function RasEntryDlgA; external rasapi32 name 'RasEntryDlgA';
function RasCreatePhonebookEntryA; external rasapi32 name 'RasCreatePhonebookEntryA';
function RasGetProjectionInfoA; external rasapi32 name 'RasGetProjectionInfoA';

{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}

end.

有了这些函数,然后可以做自己的拨号程序了

program AutoDial;

{$APPTYPE CONSOLE}

uses
  SysUtils,IniFiles,Windows,Winsock,
  Ras in 'ras.pas';

var
  DirPath,EntryName,UserName,PassWord,VisitHost,VisitUrl,VisitParam:string;
  CheckVisit:Boolean;
  nRasConnCount: DWORD;
  aRasConn:array [0..10] of TRASCONN;
  hRasConn:THRASCONN;
  f:TIniFile;
  IsConnected:boolean;
 
procedure LogMessage(Msg:string);
var
  LogFile:TextFile;
begin
  try
    AssignFile(LogFile,DirPath+'Log.txt');
    Append(LogFile);
    WriteLn(LogFile,DateTimeToStr(Now)+','+Msg);
    CloseFile(LogFile);
    WriteLn(DateTimeToStr(Now)+','+Msg);
  except
  end;

end;

function GetIP:string;
var
    IPAddr : String;
begin
    IPAddr := RasGetIPAddress;
    if IPAddr > '' then
        result:=IPAddr
    else
        result:='Unknown';
end;

function InitSocket(var ASocket:TSocket;AAddr:string;APort:integer;ATimeOut:integer):integer;
var
  MyWSA: WSAData;
  SIN: TSockAddr;
begin
  Result:=0;
  If WSAStartup(MAKEWORD(2,2), MyWSA) <> 0 Then  //初始化
  Begin
    WSACleanup;
    Result:=1;
    Exit;
  end;
  ASocket:=Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //创建socket
  If ASocket = INVALID_SOCKET Then
  Begin
    WSACleanup;
    Result:=2;
    Exit;
  End;
  SIN.sin_family := AF_INET;
  SIN.sin_port := htons(APort);
  SIN.sin_addr.S_addr := inet_addr(PChar(AAddr));
  If connect(ASocket, SIN, SizeOf(SIN)) = SOCKET_ERROR Then
  Begin
    CloseSocket(ASocket);
    WSACleanup;
    Result:=9;
    Exit;
  end;
  if SetSockOpt(ASocket,SOL_SOCKET,SO_RCVTIMEO,PChar(@ATimeOut),SizeOf(ATimeOut))=SOCKET_ERROR then //设置接收超时为3秒
  begin
    CloseSocket(ASocket);
    WSACleanup;
    Result:=6;
    Exit;
  end;
  if SetSockOpt(ASocket,SOL_SOCKET,SO_SNDTIMEO,PChar(@ATimeOut),SizeOf(ATimeOut))=SOCKET_ERROR then //设置发送超时为3秒
  begin
    CloseSocket(ASocket);
    WSACleanup;
    Result:=7;
    Exit;
  end;
end;

procedure UninitSocket(ASocket:TSocket);
begin
  try
    CloseSocket(ASocket); //关闭socket
    WSACleanup;
  except
  end;
end;

procedure AfterConnect;//等拨号完成后,访问指定页面,借此将ip地址记录下来,这样我们就可以在其他地方知道拨号后新的ip地址了
var
  hSocket: TSocket;
  SAddr,sendtext:string;
  Sendbuf:array[0..1024] of char;
  HostEnt:PHostEnt;

begin
  try
    if not CheckVisit then
    begin
      LogMessage('----------'+GetIp+'----------');
      IsConnected:=True;
      exit;
    end;

    HostEnt:=gethostbyname(pchar(VisitHost));
    if HostEnt<>nil then
    begin
     with HostEnt^ do
        SAddr:=Format('%d.%d.%d.%d',[byte(h_addr^[0]),byte(h_addr^[1]),byte(h_addr^[2]),byte(h_addr^[3])]);
    end;

    InitSocket(hSocket,SAddr,80,10000);
    sendtext:='POST '+VisitUrl+' HTTP/1.1'+#13#10
               +'Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*'+#13#10
               +'Referer: '+#13#10
               +'Accept-Language: zh-cn'+#13#10
               +'Content-Type: application/x-www-form-urlencoded'+#13#10
               +'Accept-Encoding: gzip, deflate'+#13#10
               +'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705)'+#13#10
               +'Host: '+VisitHost+#13#10
               +'Content-Length: '+inttostr(length(VisitParam))+#13#10
               +'Connection: Keep-Alive'+#13#10
               +'Cache-Control: no-cache'+#13#10
               +'Cookie: '+#13#10
               +#13#10
               +VisitParam+#13#10;
    FillChar(sendbuf,sizeof(sendbuf),0);
    StrLCopy(sendbuf,PChar(sendtext),length(sendtext));
    Send(hSocket,sendbuf,length(sendtext),0);

    UninitSocket(hSocket);

    LogMessage('----------'+GetIp+'----------');
    IsConnected:=True;
  except
  end;
end;

procedure Disconnected;
begin
  try
    if hRasConn <> 0 then
    begin
      RasHangUpA(hRasConn);
      hRasConn:= 0;
    end;
  except
  end;
end;

procedure GetActiveConn;
var
    dwRet    : DWORD;
    nCB      : DWORD;
    Buf      : array [0..255] of Char;
begin
  try
    aRasConn[0].dwSize := SizeOf(aRasConn[0]);
    nCB   := SizeOf(aRasConn);
    dwRet := RasEnumConnectionsA(@aRasConn, @nCB, @nRasConnCount);
    if dwRet <> 0 then begin
        RasGetErrorStringA(dwRet, @Buf[0], SizeOf(Buf));
        LogMessage(Buf);
    end;
  except
  end;
end;

function GetActiveConnHandle(szName : String) : THRASCONN;
var
    I : Integer;
begin
    GetActiveConn;
    if nRasConnCount > 0 then begin
        for I := 0 to nRasConnCount - 1 do begin
            if StrIComp(PChar(szName), aRasConn[I].szEntryName) = 0 then begin
                Result := aRasConn[I].hRasConn;
                Exit;
            end;
        end;
    end;
    Result := 0;
end;

function CheckConn(FEntryName:string):boolean;
begin
    hRasConn := GetActiveConnHandle(FEntryName);
    if hRasConn <> 0 then
      result:=True
    else
      Result:=False;
end;

procedure RasDialFunc(unMsg : DWORD;FRasConnState : TRASCONNSTATE;FdwError : DWORD); stdcall;
var
  Buf: array [0..255] of Char;
begin
  try
    LogMessage(RasConnectionStateToString(FRasConnState));
    if FRasConnState = RASCS_Connected then begin
        AfterConnect;
    end
    else if FRasConnState = RASCS_Disconnected then begin
        RasGetErrorStringA(FdwError, @Buf[0], SizeOf(Buf));
        LogMessage(Buf);
        Disconnected;
    end;
  except
  end;

end;

procedure Dial(FEntryName, FUserName, FPassword : String);
var
    rdParams : TRASDIALPARAMS;
    dwRet    : DWORD;
    Buf      : array [0..255] of Char;
begin
  try
    hRasConn := GetActiveConnHandle(FEntryName);
    if hRasConn <> 0 then begin
        LogMessage('Connection already active');
        Exit;
    end;

    // setup RAS Dial Parameters
    FillChar(rdParams, SizeOf(rdParams), 0);
    rdParams.dwSize              := SizeOf(TRASDIALPARAMS);
    strCopy(rdParams.szUserName,  PChar(FUserName));
    strCopy(rdParams.szPassword,  PChar(FPassword));
    strCopy(rdParams.szEntryName, PChar(FEntryName));
    rdParams.szPhoneNumber[0]    := #0;
    rdParams.szCallbackNumber[0] := '*';
    rdParams.szDomain            := '*';

    hRasConn := 0;;
    dwRet  := RasDialA(nil, nil, @rdParams, 0, @RasDialFunc, @hRasConn);
    if dwRet <> 0 then
    begin
        RasGetErrorStringA(dwRet, @Buf[0], SizeOf(Buf));
        LogMessage(IntToStr(dwRet) + ' ' + Buf);
        Disconnected;
    end
    else
    begin
        LogMessage('Dialing ''' + FEntryName + '''');
    end;
  except
  end;
end;

begin
  try
    DirPath:=ExtractFilePath(ParamStr(0));
    f:=TiniFile.Create(DirPath+'conf.ini');
    EntryName:=f.ReadString('RasDial','EntryName','');
    UserName:=f.ReadString('RasDial','UserName','');
    PassWord:=f.ReadString('RasDial','PassWord','');
    CheckVisit:=f.ReadBool('RasDial','Visit',False);
    VisitHost:=f.ReadString('RasDial','Host','');
    VisitUrl:=f.ReadString('RasDial','Url','');
    VisitParam:=f.ReadString('RasDial','Param','');
    f.Free;

    if not CheckConn(EntryName) then
    begin

        Dial(EntryName,UserName,PassWord);

    end
    else
    begin
      LogMessage('----------'+GetIp+'----------');
      IsConnected:=True;
    end;
    while not IsConnected do
      sleep(1000);
  except
  end;   
end.

然后编译后产生一个console application,
编写自己的conf.ini,填入自己的连接名称,用户名,密码等参数
运行该程序,就可以自动拨号了。

源码下载

http://ono.3322.org

本文地址:http://com.8s8s.com/it/it5429.htm