怎么Delphi中操縱撥號網(wǎng)絡(luò)
發(fā)表時(shí)間:2023-07-15 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]用MODEM撥號上網(wǎng),仍是大多數(shù)個(gè)人網(wǎng)民選擇上網(wǎng)的方式.如果能在我們的應(yīng)用程序中管理撥號 網(wǎng)絡(luò)(如Foxmail、Sygate中的撥號功能),無疑將會方便我們的軟件用戶(不用再切換應(yīng)用程序, 運(yùn)行撥...
用MODEM撥號上網(wǎng),仍是大多數(shù)個(gè)人網(wǎng)民選擇上網(wǎng)的方式.如果能在我們的應(yīng)用程序中管理撥號 網(wǎng)絡(luò)(如Foxmail、Sygate中的撥號功能),無疑將會方便我們的軟件用戶(不用再切換應(yīng)用程序, 運(yùn)行撥號網(wǎng)絡(luò)),提高我們的軟件的友好性從而提高軟件的競爭力.
在WIN9X下,如果安裝了撥號網(wǎng)絡(luò),則在WINDOWS系統(tǒng)的系統(tǒng)目錄System下將有兩個(gè)撥號網(wǎng)絡(luò)管理 程序庫RasApi32.DLL和RasApi16.DLL,我們可利用其中的函數(shù)來獲取和設(shè)置撥號連接網(wǎng)絡(luò)的信息。在 Delphi幫助文件中,有相關(guān)函數(shù)的說明。
在此,我們要討論的管理項(xiàng)目有:
1、獲取當(dāng)前系統(tǒng)中可用的撥號連接名稱
2、新建撥號連接、修改撥號連接的屬性
3、獲取和設(shè)置撥號連接的撥號參數(shù)
4、用指定的撥號連接撥號、掛斷指定的撥號連接
5、獲取當(dāng)前活動的連接及其連接狀態(tài)零、獲取RasAPI函數(shù)執(zhí)行失敗的錯(cuò)誤信息
RasAPI的調(diào)用接口是統(tǒng)一的,但對于不同的Windows版本,許多常量和數(shù)據(jù)結(jié)構(gòu)的定義是不同的。 如果使用的數(shù)據(jù)結(jié)構(gòu)與Windows版本不對應(yīng),RasAPI函數(shù)執(zhí)行會失敗;另外,其它原因如其它程序也 在使用同一個(gè)撥號連接進(jìn)行撥號等,也會造成RasAPI函數(shù)執(zhí)行失敗.鑒于此原因,我們需要先討論獲 取RasAPI函數(shù)執(zhí)行失敗的錯(cuò)誤信息的函數(shù)。
當(dāng)一個(gè)RasAPI函數(shù)執(zhí)行結(jié)束時(shí),會返回一個(gè)結(jié)果標(biāo)識,為0時(shí)表示執(zhí)行成功,否則作為一個(gè)錯(cuò)誤標(biāo) 識符表示執(zhí)行失敗的原因。RasAPI函數(shù)RasGetErrorString可以根據(jù)錯(cuò)誤標(biāo)識符返回其錯(cuò)誤描述信息,
在中文WIN9X下可提供一個(gè)中文錯(cuò)誤信息.
RasGetErrorString的函數(shù)原型為:
function RasGetErrorString (
uErrorValue : UINT;//錯(cuò)誤標(biāo)識符
lpszErrorString : PChar;//錯(cuò)誤提示信息的緩沖區(qū)
cBufSize : DWORD//錯(cuò)誤提示信息的緩沖區(qū)大小
) : DWORD; stdcall;
function RasGetErrorString;external RasApiDll name 'RasGetErrorStringA';
( 注:RasApiDll = 'Rasapi32.dll'; )
為了方便,我們可以自己編寫一個(gè)函數(shù),用于獲取RasAPI函數(shù)執(zhí)行失敗的錯(cuò)誤信息。在下面的例
子中,會經(jīng)常用到該函數(shù)。函數(shù)代碼如下所示:
{ 根據(jù)錯(cuò)誤標(biāo)識符,獲取RasAPI函數(shù)執(zhí)行失敗的錯(cuò)誤信息 }
function GetRasError( ErrorID : UINT ) : string;
var
buffer : array[ 0..255 ] of char;
begin
if 0 = RasGetErrorString( ErrorID
buffer
256 ) then
result := strpas( buffer )//如果能正確返回錯(cuò)誤信息,則轉(zhuǎn)化為Pascal字符串
else//否則返回16進(jìn)制形式的錯(cuò)誤代碼
result := 'GetRasError Failure:ErrorID=' + Format( '%x'
[ErrorID] );
end;
一、獲取當(dāng)前系統(tǒng)中可用的撥號連接名稱
即獲取系統(tǒng)中已建立的撥號連接的名稱,可用來讓用戶選擇使用哪個(gè)撥號連接進(jìn)行撥號.
可以用兩種方法來實(shí)現(xiàn).一種是利用RasAPI函數(shù);另一種是不用RasAPI函數(shù),直接在注冊表中查詢.
1、不用RasAPI函數(shù),直接在注冊表中查詢
在注冊表的HKEY_USERS\.Default\RemoteAccess\Addresses下,列出了已經(jīng)在撥號網(wǎng)絡(luò)中建立的撥號連接的名稱及其屬性設(shè)置,其中各項(xiàng)目的名稱即為可用的撥號連接的名稱;各項(xiàng)目的值即為各撥號連接的屬性設(shè)置,不過是二進(jìn)制串,筆者還看不懂.由此可見,我們只要讀出各項(xiàng)目的名稱即可獲取當(dāng)前系統(tǒng)中可用的撥號連接名稱.
var
registryTemp : TRegistry;
stringsTemp : TStringlist;
begin
registryTemp := TRegistry.Create;
stringsTemp := TStringlist.Create;
with registryTemp do
begin
RootKey := HKEY_USERS;//根鍵設(shè)置為HKEY_USERS
//如果存在子鍵.Default\RemoteAccess\Addresses
if OpenKey('.Default\RemoteAccess\Addresses'
false) then
GetValueNames( stringsTemp );//讀出各項(xiàng)目的名稱,即撥號連接名稱
end;
combobox1.Items.assign( stringsTemp );//顯示,供選擇
end;
2、用RasAPI函數(shù)
RasAPI函數(shù)RasEnumEntries可獲取當(dāng)前系統(tǒng)中可用的撥號連接名稱.其函數(shù)原型為
function RasEnumEntries(reserved : PChar;//保留字段
必須為NIL
lpszPhonebook : PChar;//電話本名稱
在Win9X下無作用
可為空字符串
lprasentryname : LPRASENTRYNAME;//接收撥號連接名稱的緩沖區(qū)
是一個(gè)RASENTRYNAME類型數(shù)組的指針
var lpcb : DWORD;//接收撥號連接名稱的緩沖區(qū)的大小(Bytes)
var lpcEntries: DWORD//實(shí)際獲得的撥號連接名稱的數(shù)目
) : DWORD; stdcall;
function RasEnumEntries;external RasApiDll name 'RasEnumEntriesA';
參數(shù)lprasentryname提供了一個(gè)RASENTRYNAME類型數(shù)組的指針,指向一個(gè)接收撥號連接名稱的緩沖區(qū),其中RASENTRYNAME及LPRASENTRYNAME的類型說明如下:
LPRASENTRYNAME = ^RASENTRYNAME;
RASENTRYNAME = record
dwSize : DWORD;//該結(jié)構(gòu)所占內(nèi)存的大小(Bytes)
一般設(shè)置為SizeOf(RASENTRYNAME)
szEntryName : array [ 0..RAS_MaxEntryName ] of char;//撥號連接名稱
end;
lpcb為緩沖區(qū)的大小,一般設(shè)置為dwSize的倍數(shù),倍數(shù)為可能有的連接的個(gè)數(shù).
lpcEntries實(shí)際的連接的個(gè)數(shù).
下面是一個(gè)應(yīng)用例子,列出了當(dāng)前系統(tǒng)中可用的撥號連接名稱.
注意,應(yīng)在RASENTRYNAME緩沖區(qū)的第一個(gè)RASENTRYNAME結(jié)構(gòu)中設(shè)置dwSize.
const MaxPhoneEntries = 10;//最多的撥號連接數(shù)目
var intIndex : integer;
PhoneEntries : array[ 0..MaxPhoneEntries - 1 ] of RASEntryName;
dwSize
dwEntries
dwResult : DWORD;
begin
//在RASENTRYNAME緩沖區(qū)的第一個(gè)RASENTRYNAME結(jié)構(gòu)中設(shè)置dwSize
PhoneEntries[ 0 ].dwSize := sizeof( RASEntryName );
dwSize := MaxPhoneEntries * sizeof( RASEntryName );//為緩沖區(qū)的大小
//調(diào)用RasAPI函數(shù),獲取當(dāng)前系統(tǒng)中可用的撥號連接名稱
dwResult := RasEnumEntries ( NIL
''
@PhoneEntries[ 0 ]
dwSize
dwEntries );
if dwResult <> 0 then
begin//RasAPI函數(shù),執(zhí)行錯(cuò)誤
memo1.lines.add('RasEnumEntries錯(cuò)誤:' + GetRasError( dwResult ));
exit;
end;
//顯示當(dāng)前系統(tǒng)中可用的撥號連接名稱
memo1.lines.add('共有' + inttostr( dwEntries ) + '個(gè)RAS連接,如下所示');
for intIndex := 0 to dwEntries -1 do
memo1.lines.add( strpas( PhoneEntries[ intIndex ].szEntryName ) );
end;
3、獲取默認(rèn)的撥號連接的名稱
默認(rèn)的撥號連接,即用戶在瀏覽器中設(shè)置的撥號連接,該連接可以認(rèn)為是用戶最常用撥號連接.
在注冊表的HKEY_USERS\.Default\RemoteAccess位置,有一個(gè)字符串名Profile,它對應(yīng)字符值即為HKEY_USERS\.Default\RemoteAccess\Addresses.
二、新建撥號連接、修改撥號連接的屬性
RasAPI函數(shù)RasCreatePhonebookEntry、RasEditPhonebookEntry通過調(diào)用Win9X的
新建撥號連接、修改撥號連接的設(shè)置界面,允許用戶新建撥號連接、修改撥號連接,具體的設(shè)置操作還要由系統(tǒng)來完成.
1、新建撥號連接
新建撥號連接的RasAPI函數(shù)為RasCreatePhonebookEntry,其函數(shù)原型為:
function RasCreatePhonebookEntry(
hwnd : THandle; //新建撥號連接窗口的父窗口的句柄,為NIL表示桌面(DeskTop)
lpszPhonebook: pchar//電話本名稱
在Win9X下無作用
可為空字符串
) : DWORD;stdcall;
function RasCreatePhonebookEntry;external RasApiDll name 'RasCreatePhonebookEntryA';
函數(shù)返回值為0表示執(zhí)行成功;否則為錯(cuò)誤代碼.
下面是一個(gè)應(yīng)用例子,允許用戶新建一個(gè)撥號連接.
var
dwResult : DWORD;
begin
//在當(dāng)前窗口中新建撥號連接
dwResult := RasCreatePhonebookEntry( handle
'' );
if dwResult = 0 then
memo1.lines.add('新建撥號連接成功!')
else
memo1.lines.add('新建撥號連接失敗:!' + GetRasError( dwResult ))
end;
2、修改撥號連接的屬性
修改撥號連接的屬性的RasAPI函數(shù)為RasEditPhonebookEntry,其函數(shù)原型為:
function RasEditPhonebookEntry(
hwnd : THandle; //新建撥號連接窗口的父窗口的句柄,為NIL表示桌面(DeskTop)
lpszPhonebook: pchar;//電話本名稱,在Win9X下無作用
可為空字符串
lpszEntryName: pchar//撥號連接的名稱,如'163'、'169'等
) : DWORD; stdcall;
function RasEditPhonebookEntry;external RasApiDll name 'RasEditPhonebookEntryA';
函數(shù)返回值為0表示執(zhí)行成功;否則為錯(cuò)誤代碼.
下面是一個(gè)應(yīng)用例子,允許用戶修改指定撥號連接的屬性.
var
dwResult : DWORD;
begin
//在當(dāng)前窗口中修改撥號連接的屬性
dwResult := RasEditPhonebookEntry( handle
''
'163' );
if dwResult = 0 then
memo1.lines.add('修改撥號連接成功!')
else
memo1.lines.add('修改撥號連接失敗:!' + GetRasError( dwResult ))
end;
三、獲取和設(shè)置撥號連接的撥號參數(shù)
用RasAPI函數(shù)RasGetEntryDialParams、RasSetEntryDialParams可以直接獲取和設(shè)置指定撥號連接的撥號參數(shù),其中包括用戶名稱和用戶密碼!
1、獲取撥號連接的撥號參數(shù)
獲取撥號連接的撥號參數(shù)RasAPI函數(shù)為RasGetEntryDialParams,其函數(shù)原型為:
function RasGetEntryDialParams(
lpszPhonebook: pchar;//電話本名稱,在Win9X下無作用
可為空字符串
pRASDIALPARAMS:LPRASDIALPARAMS;//撥號參數(shù),是一個(gè)RASDIALPARAMS類型的指針
var lpfPassword : WordBool//是否需要用戶密碼
) : DWORD; stdcall;
function RasGetEntryDialParams;external RasApiDll name 'RasGetEntryDialParamsA';
參數(shù)pRASDIALPARAMS是一個(gè)RASDIALPARAMS類型的指針,指向一個(gè)撥號連接的撥號參數(shù)數(shù)據(jù) 的緩沖區(qū),其中RASDIALPARAMS及LPRASDIALPARAMS的類型說明如下:
LPRASDIALPARAMS = ^RASDIALPARAMS;
RASDIALPARAMS = record
dwSize : DWORD;//該結(jié)構(gòu)所占內(nèi)存的大小(Bytes)
一般設(shè)置為SizeOf(RASDIALPARAMS)
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;//域名
end;
函數(shù)返回值為0表示執(zhí)行成功;否則為錯(cuò)誤代碼.
下面是一個(gè)應(yīng)用例子,獲取指定撥號連接的撥號參數(shù).
var
dwResult : DWORD;
RASDIALPARAMSData : RASDIALPARAMS;
NeedPWD : WordBool;
begin
//指定撥號連接的名稱
with RASDIALPARAMSData do
begin
dwSize := sizeof( RASDIALPARAMS );//結(jié)構(gòu)大小
szEntryName := '163';//指定撥號連接的名稱
szUserName := '';//其它五個(gè)參數(shù)初始化
szPassword := '';
szDomain := '';
szCallbackNumber := '';
szPhoneNumber := '';
end;
NeedPWD := true;//需要用戶密碼
//獲取指定撥號連接的撥號參數(shù)
dwResult := RasGetEntryDialParams( ''
@RASDIALPARAMSData
NeedPWD );
if dwResult <> 0 then //獲取指定撥號連接的撥號參數(shù)失敗
memo1.lines.add( '獲取'+StrPAS(RASDIALPARAMSData.szEntryName )+'撥號參數(shù)失敗:'
+ GetRasError( dwResult ))
else
begin//顯示指定撥號連接的撥號參數(shù)
memo1.lines.add( StrPAS(RASDIALPARAMSData.szEntryName )+'撥號參數(shù)如下');
memo1.lines.add( '用戶名稱:' + StrPAS(RASDIALPARAMSData.szUserName ));
memo1.lines.add( '用戶密碼:' + StrPAS(RASDIALPARAMSData.szPassword ));
memo1.lines.add( '域 名:' + StrPAS(RASDIALPARAMSData.szDomain ));
memo1.lines.add( '回叫號碼:' + StrPAS(RASDIALPARAMSData.szCallbackNumber ));
memo1.lines.add( '撥號號碼:' + StrPAS(RASDIALPARAMSData.szPhoneNumber ));
end;
end;
2、設(shè)置撥號連接的撥號參數(shù)
設(shè)置撥號連接的撥號參數(shù)RasAPI函數(shù)為RasSetEntryDialParams,其函數(shù)原型為:
function RasSetEntryDialParams(
lpszPhonebook: pchar;//電話本名稱,在Win9X下無作用
可為空字符串
pRASDIALPARAMS:LPRASDIALPARAMS;//撥號參數(shù),是一個(gè)RASDIALPARAMS類型的指針
var lpfPassword : WordBool//是否刪除用戶密碼
) : DWORD; stdcall;
function RasSetEntryDialParams;external RasApiDll name 'RasSetEntryDialParamsA';
參數(shù)pRASDIALPARAMS的說明同RasGetEntryDialParams.
參數(shù)lpfPassword的含義與RasGetEntryDialParams不同,在此表示是否刪除用戶密碼,為
TRUE時(shí)將原來的用戶密碼刪除.
函數(shù)返回值為0表示執(zhí)行成功;否則為錯(cuò)誤代碼.
下面是一個(gè)應(yīng)用例子,設(shè)置指定撥號連接的撥號參數(shù).
var
dwResult : DWORD;
RASDIALPARAMSData : RASDIALPARAMS;
RemovePWD : WordBool;
begin
//指定撥號連接的撥號參數(shù)
with RASDIALPARAMSData do
begin
dwSize := sizeof( RASDIALPARAMS );//結(jié)構(gòu)大小
szEntryName := '163';//指定撥號連接的名稱
szUserName := 'MyName';//指定用戶名稱
szPassword := 'MyPassword';//指定用戶密碼
szDomain := 'MyDomain';//指定域名
szCallbackNumber := '';//指定回叫號碼
szPhoneNumber := '';//指定撥號號碼
end;
RemovePWD := false;//不需要刪除用戶密碼
//設(shè)置指定撥號連接的撥號參數(shù)
dwResult := RasSetEntryDialParams( ''
@RASDIALPARAMSData
RemovePWD );
if dwResult <> 0 then //設(shè)置指定撥號連接的撥號參數(shù)失敗
memo1.lines.add( '設(shè)置'+StrPAS(RASDIALPARAMSData.szEntryName )+'撥號參數(shù)失敗:' + GetRasError( dwResult ))
else
begin//顯示指定撥號連接的撥號參數(shù)
memo1.lines.add( StrPAS(RASDIALPARAMSData.szEntryName )+'撥號參數(shù)設(shè)置成功');
memo1.lines.add( '用戶名稱:' + StrPAS(RASDIALPARAMSData.szUserName ));
memo1.lines.add( '用戶密碼:' + StrPAS(RASDIALPARAMSData.szPassword ));
memo1.lines.add( '域 名:' + StrPAS(RASDIALPARAMSData.szDomain ));
memo1.lines.add( '回叫號碼:' + StrPAS(RASDIALPARAMSData.szCallbackNumber ));
memo1.lines.add( '撥號號碼:' + StrPAS(RASDIALPARAMSData.szPhoneNumber ));
end;
end;
四、用指定的撥號連接撥號、掛斷指定的撥號連接
1、用指定的撥號連接撥號
撥號有兩種方法,一種是調(diào)用撥號網(wǎng)絡(luò)中的撥號程序,就象用戶自己用鼠標(biāo)雙擊撥號連接名稱一 樣,用戶可以修改撥號號碼、用戶名稱和用戶密碼,最后由撥號網(wǎng)絡(luò)來完成撥號過程;另一個(gè)方法則 是調(diào)用RasAPI函數(shù).
(1)用撥號網(wǎng)絡(luò)中的撥號程序
在程序中可以用如下代碼:
winexec('rundll32.exe rnaui.dll
RnaDial 169'
SW_SHOWNORMAL);
其中字符串中的最后一個(gè)參數(shù)"169"為撥號連接的名稱。
(2)用RasAPI函數(shù)撥號 用撥號連接撥號的RasAPI函數(shù)為RasDial,其函數(shù)原型為:
function RasDial(
pRasDialExtensions : LPRASDIALEXTENSIONS;//在WIN9X下無用
可設(shè)置為NIL
lpszPhonebook : PChar;//電話本名稱,在Win9X下無作用
可為空字符串
lpRasDialParams : LPRASDIALPARAMS;//撥號參數(shù)
dwNotifierType : DWORD;//消息通知方式
handle : TRasDialFunc;//消息處理事件
var lphRasConn : DWORD//返回的成功連接的連接句柄
) : DWORD; stdcall;
function RasDial;external RasApiDll name 'RasDialA';
參數(shù)pRASDIALPARAMS的說明同RasGetEntryDialParams.
參數(shù)dwNotifierType表示消息通知方式.在撥號過程中,系統(tǒng)發(fā)出撥號事件消息可以通知撥號 進(jìn)度,因而需要提供接受消息的方式和處理消息的函數(shù).當(dāng)其值為$FFFFFFFF時(shí),則參數(shù)handle被 視為一個(gè)窗口的句柄,事件消息被發(fā)生該窗口處理;當(dāng)其值為0時(shí),handle被視為TRasDialFunc類型 的函數(shù)的指針;當(dāng)其值為1時(shí),handle被視為TRasDialFunc1類型的函數(shù)的指針.
參數(shù)handle表示消息處理函數(shù)指針,其類型可以THandle、TRasDialFunc、TRasDialFunc1.當(dāng)該 參數(shù)不為NULL或NIL時(shí),其代表的消息處理函數(shù)指針將接受撥號進(jìn)度通知消息;為NIL時(shí),撥號過程由異步方式變?yōu)橥椒绞剑钡綋芴栠^程成功或失敗后RasDial函數(shù)才返回.詳細(xì)可參見Delphi幫助文件中關(guān)于RasDial函數(shù)的幫助。
當(dāng)撥號連接成功時(shí),lphRasConn將表示其連接句柄.
函數(shù)返回值為0表示執(zhí)行成功;否則為錯(cuò)誤代碼.
下面是一個(gè)應(yīng)用例子,按指定的撥號參數(shù)撥號.
var
RASDIALPARAMSData : RASDIALPARAMS;
dwResult : DWord;
RasCon : DWord;
begin
//指定撥號連接的撥號參數(shù)
with RASDIALPARAMSData do
begin
dwSize := sizeof( RASDIALPARAMS );//結(jié)構(gòu)大小
szEntryName := '163';//指定撥號連接的名稱
szUserName := 'MyName';//指定用戶名稱
szPassword := 'MyPassword';//指定用戶密碼
szDomain := 'MyDomain';//指定域名
szCallbackNumber := '';//指定回叫號碼
szPhoneNumber := '';//指定撥號號碼
end;
//用指定的撥號參數(shù)撥號,采用同步撥號方式
dwResult := RasDial( NIL
''
@RASDIALPARAMSData
0
NIL
RasCon );
if dwResult <> 0 then //設(shè)置指定撥號連接的撥號參數(shù)失敗
memo1.lines.add( '用'+StrPAS(RASDIALPARAMSData.szEntryName )+'撥號失敗:'
+ GetRasError( dwResult ))
else
memo1.lines.add( '用'+StrPAS(RASDIALPARAMSData.szEntryName )+'撥號成功!' );
end;
2、掛斷指定的撥號連接
掛斷撥號連接的RasAPI函數(shù)為RasHangUp,其函數(shù)原型為:
function RasHangUp(
hRasConn : DWORD//要掛斷的撥號連接的句柄
) : DWORD; stdcall;
function RasHangUp;external RasApiDll name 'RasHangUpA';
函數(shù)返回值為0表示執(zhí)行成功;否則為錯(cuò)誤代碼.
下面是一個(gè)應(yīng)用例子,掛斷由RasDial建立的撥號連接.
//掛斷由RasDial建立的撥號連接
dwResult := RasHangUp( RasCon );
if dwResult <> 0 then //掛斷失敗
memo1.lines.add( '掛斷失敗:' + GetRasError( dwResult ))
else
memo1.lines.add( '掛斷成功!');
五、獲取當(dāng)前活動的連接及其連接狀態(tài)
1、獲取當(dāng)前活動的連接
獲取當(dāng)前活動的連接的RasAPI函數(shù)為RasEnumConnections,其函數(shù)原型為:
DWORD RasEnumConnections(
LPRASCONN lprasconn, // buffer to receive connections
// data
LPDWORD lpcb, // size in bytes of buffer
LPDWORD lpcConnections // number of connections written
// to buffer
);