摘 要:主要論述了如何運用Delphi編程實現自動釋放、自動獲得本地系統所有動態IP地址,以及在Delphi中如何使用Netsh.exe公用程式更改網路設定資訊,並給出了相應的樣本程式。
關鍵詞:Delphi,IP地址,Netsh
一、 引言
隨著Internet的普及,網路安全問題日益突出,根據國家有關部門的政策,在大多數安全程度要求高的機關單位都建立了物理隔離的內、外網路。在這種環境下,各工作站需在不同網段的內、外網之間頻繁切換,這就要求工作站系統的網路設定需要及時更新。另外,隨著隨處工作的普及,膝上型電腦系統的網路設定同樣需要經常改變。Delphi作為最優秀的開發工具,用“Delphi + Windows API”模式可很好地解決這些問題。
二、原理
IP Helper 是一套用於管理本網設定的API(API),這些API函數在iphlpapi.dll庫檔案中被定義。iphlpapi.dll庫檔案存在於Windows NT4/2000/System32 目錄下或Windows 98/Me 的 /System目錄。就象在VC中編寫標頭檔一樣,在delphi中使用這些API需要進行相應的定義和聲明。
一台電腦可能安裝一塊以上網路介面卡或存在Modem,調用GetAdaptersInfo函數可獲得當前電腦網路設定資訊。這個函數包含兩個參數,第一個參數是用來儲存適配器資訊的記憶體緩衝的首地址,而第二個參數是這個緩衝的大小。由於我們事先不知道本地機器上有多少個網路介面卡,所以也就沒法知道應該分配多大的緩衝,好在GetAdaptersInfo函數在緩衝的大小不夠時會在第二個參數中填入應該分配的緩衝的大小,因此,就象其它一些函數一樣在需要時我們可以兩次調用該函數,第一次是擷取緩衝區的大小,然後分配這個緩衝以後再次調用它以獲得實際的網卡資訊。函數定義如下:
function GetAdaptersInfo( pAdapterInfo: PTIP_ADAPTER_INFO;
pOutBufLen: PULONG ): DWORD;
stdcall; external 'IPHLPAPI.DLL';
函數返回的當前電腦網路設定資訊存在於第一個參數pAdapterInfo指向的IP_ADAPTER_INFO結構,該資料結構是以靜態鏈表的方式組織的。
PIpAdapterInfo = ^TIpAdapterInfo;
TIP_ADAPTER_INFO = record
Next: PIpAdapterInfo; //鏈表指標域,通過它訪問整個靜態鍵表
ComboIndex: DWORD; //保留未用
AdapterName: //網卡名,max_adapter_name_length=256
array [0..MAX_ADAPTER_NAME_LENGTH + 3] of Char;
Description: //對網卡的描述max_adapter_description_length=128
array [0..MAX_ADAPTER_DESCRIPTION_LENGTH + 3] of Char;
AddressLength: UINT; //物理地址的長度
Address: //物理地址,max_adapter_address_length=8每個位元組存放一個十六進位的數
array [0..MAX_ADAPTER_ADDRESS_LENGTH - 1] of BYTE;
Index: DWORD; //網卡索引號
Type_: UINT; //網卡類型
DhcpEnabled: UINT; //是否啟用了DHCP動態IP分配
CurrentIpAddress: PIP_ADDR_STRING; //當前使用的IP地址
IpAddressList: IP_ADDR_STRING; //綁定到此網卡的IP地址鏈表
GatewayList: IP_ADDR_STRING; //網關地址鏈表
DhcpServer: IP_ADDR_STRING; //DHCP伺服器位址,只有在DhcpEnabled==TRUE的情況下才有效
HaveWins: BOOL; //是否啟用了WINS
PrimaryWinsServer: IP_ADDR_STRING; //主WINS地址
SecondaryWinsServer: IP_ADDR_STRING; //輔WINS地址
LeaseObtained: time_t; //當前DHCP租借擷取的時間
LeaseExpires: time_t; //當前DHCP租借失效時間
end;
這些資料就是網路屬性→TCP/IP的屬性頁面裡的內容。使用這些資訊可進行網路設定資訊的更改,下面說明如何更新動態IP和修改靜態網路設定資訊。
2.1 DhcpEnabled = 1 則說明本地IP為DHCP伺服器動態分配,調用IpReleaseAddress和IpRenewAddress可釋放、重新獲得系統IP地址。函數定義如下:
function IpRenewAddress(
var AdapterInfo: TIP_ADAPTER_INDEX_MAP): DWORD;
stdcall; external 'IPHLPAPI.DLL';
function IpReleaseAddress(
var AdapterInfo: TIP_ADAPTER_INDEX_MAP): DWORD;
stdcall;external 'IPHLPAPI.DLL';
使用這兩個函數必需擷取網路介面資訊,以指定釋放、更新IP地址的適配器索引號。一個網路介面是網卡的邏輯抽象,它們是一對一的關係。注意調用GetNumberOfInterfaces函數返回本機介面的數量,實際上比網路介面數目多一個,因為每個系統都附加有一個調試用的網路介面,這個介面的IP地址是127.0.0.1子網路遮罩是255.0.0.0。GetInterfaceInfo函數提取網路介面的資訊:
function GetInterfaceInfo(pIfTable: PTIP_INTERFACE_INFO;
dwOutBufLen: PULONG): DWORD;
stdcall; external 'IPHLPAPI.DLL';
它返回IP_INTERFACE_INFO結構中有一個NumAdapters整型的資料域記錄了當前本機適配器數量,Adapter為IP_ADAPTER_INDEX_MAP結構的資料數組。
PIP_INTERFACE_INFO = ^TIP_INTERFACE_INFO;
TIP_INTERFACE_INFO = record
NumAdapters : Longint;
Adapter : array [0..1-1] of IP_ADAPTER_INDEX_MAP;
end;
其中的IP_ADAPTER_INDEX_MAP結構如下:
PIpAdapterIndexMap = ^TIpAdapterIndexMap;
TIP_ADAPTER_INDEX_MAP = record
Index: ULONG;
Name: array [0..127] of WCHAR;
end;
當此結構中Index值等於通過調用GetAdaptersInfo函數pAdapterInfo指向的結構中Index域的值,說明網路介面卡和網路介面相匹配,就可調用IpReleaseAddress和IpRenewAddress進行釋放、重新獲得該適配器IP地址。
2.2 在Delphi中通過直接使用Netsh.exe公用程式可改變windows2000/XP系統的IP網路設定資訊。
三、程式實現
3.1 在WIN98中運行Winipcfg公用程式, 在windows2000/XP中運行Ipconfig可釋放、重新獲得系統(所有)IP地址。下面用Delphi編程實現:
首先聲明Public IndexStrs : Tstrings; //儲存本機所有網卡索引號
procedure TForm1.Button1Click(Sender: TObject);
var
Err, BufLen : DWORD;
P : Pointer;
AdapterInfo : PTIP_ADAPTER_INFO;
begin
BufLen := SizeOf( AdapterInfo^ );
New( AdapterInfo );
Err := GetAdaptersInfo( AdapterInfo, @BufLen );
P := AdapterInfo;
IndexStrs:=Tstringlist.Create;
if Err =NO_ERROR then
begin
while P <> nil do
with TIP_ADAPTER_INFO(P^) do
begin
if DHCPEnabled = 1 then
IndexStrs.Add(inttostr(index));
P := Next; // TIP_ADAPTER_INFO(P^).Next
end // with
end // while
else
showmessage( SysErrorMessage( Error ) );
Dispose( AdapterInfo );
end;
Button1的Click事件:當本地IP為DHCP伺服器動態分配時把本地機器所有網卡索引號存於TStrings類型IndexStrs中。
procedure TForm1.Button2Click(Sender: TObject);
var
Res, Err,Suc,BufSize : DWORD;
ip_map: TIP_ADAPTER_INDEX_MAP;
cnt,dwIndex,i :Longint;
InterfaceInfo:PTIP_INTERFACE_INFO;
begin
BufSize :=sizeof(Interfaceinfo^);
Interfaceinfo := AllocMem(BufSize);
Err:= Getinterfaceinfo(Interfaceinfo,@BufSize);
if Err = ERROR_INSUFFICIENT_BUFFER then
begin
Freemem(Interfaceinfo);
Interfaceinfo := Allocmem(Bufsize);
try
Res := GetInterfaceInfo(InterfaceInfo, @BufSize);
if Res = NO_ERROR then
begin
for i:=0 to IndexStrs.Count-1 do
begin
dwindex:=StrToInt(IndexStrs[i]);
for Cnt := 0 to InterfaceInfo^.NumAdapters - 1 do
if InterFaceInfo^.Adapter[cnt].index = dwIndex then
Suc := IpReleaseAddress(InterFaceInfo^.Adapter[cnt]);
if Suc = NO_ERROR then showmessage(' 釋放IP成功! ');
end; // for i:=0 to...釋放所有IP
for i:=0 to IndexStrs.Count-1 do
begin
dwindex:=StrToInt(IndexStrs[i]);
for Cnt := 0 to InterfaceInfo^.NumAdapters - 1 do
if InterFaceInfo^.Adapter[cnt].index = dwIndex then
Suc := IpReNewAddress(InterFaceInfo^.Adapter[cnt]);
if Suc = NO_ERROR then showmessage(' 重新獲得IP成功! ');
end; // for i:=0 to...重新獲得所有IP
end;
finally
FreeMem(InterFaceInfo);
end;
end;
IndexStrs.Free;
end;
Button2的Click事件:用IndexStrs中的值匹配網路介面資訊中Index,找到相應的適配器釋放IP地址,通過迴圈釋放、重新獲得所有IP地址。
3.2 在Delphi中使用Netsh 公用程式改變網路設定。
在Windows2000以後的作業系統中都提供了Netsh.exe公用程式。Netsh 是一種命令列公用程式,一般從命令提示字元啟動 netsh 並更改到包含要使用的命令的上下文,可用來顯示或修改當前正在啟動並執行電腦的網路設定,下面說明在Delphi中使用它改變網路設定。
procedure TForm1.Button3Click(Sender: TObject);
begin
ShellExecute(Handle, 'open', 'netsh', PChar('interface ip set address "本地串連" static 192.168.0.10 255.255.255.0 192.168.0.1 1'), nil, SW_HIDE);
end;
無論當前系統IP地址是動態還是靜態,Button3Click事件把當前網路設定改為靜態IP地址192168.0.10,子網路遮罩255.255.255.0,網關:192.168.0.1,躍點數:1;同樣執行ShellExecute(Handle, 'open', 'netsh', PChar('interface ip set address "本地串連" dhcp'), nil, SW_HIDE)把本地IP地址改為動態。netsh功能強大,通過此種形式可修改、刪除、增加DNS、WINS、gateway等網路設定資訊,而且更改的資訊直接生效,不需要“禁用”→“啟用” 網卡或重新啟動windows。
四、結束語
實際上通過修改系統註冊表也可改變系統的IP地址等網路設定。不同版本作業系統網路設定資訊在註冊表中的位置不同。針對win95、win98系統的靜態IP地址通過修改註冊表來改變IP配置資訊,不過所有通過修改系統登錄機碼改變的IP配置資訊需經過 “禁用”→“啟用” 網卡或重新啟動windows才會生效。另外值得注意的是IP Help API針對win95無效。
參考文獻:
[1] PlatForm SDK: IP Helper. http://msdn.microsoft.com/library/default.asp [DB/OL],2004 – 01.
[2] Steve Teixeira,Xavier Pacheco. Delphi 5開發人員指南[M]. 任旭鈞 等譯.北京:機械工業出版社,2000