取網卡MAC號的問題 |
答題得分者是:timhuang
|
cjtsif
一般會員 發表:12 回覆:13 積分:5 註冊:2002-09-18 發送簡訊給我 |
|
shaofu
高階會員 發表:5 回覆:136 積分:103 註冊:2003-01-07 發送簡訊給我 |
引言: 站上有許多關於'取網卡MAC號'的文章, 我試過後雖可以抓出,但都有個問題, 就是該網卡必須在connect的狀態下才可取得MAC號, 也就是網路線若未接上(disconnect的狀態), 用ipconfig /all 可以取得MAC號,但程式卻抓不到, 請問各位先進,這個問題該如何解決http://community.borland.com/article/0,1410,26040,00.html ipconfig 就是用第三個方法(SNMP), Windows 系列一定都支援 |
timhuang
尊榮會員 發表:78 回覆:1815 積分:1608 註冊:2002-07-15 發送簡訊給我 |
HI, 可以用 GetAdaptersInfo 這個 api 來取得, 試過在 disconnect 的狀況下亦抓得到 mac address:
const MAX_ADAPTER_NAME_LENGTH = 256; MAX_ADAPTER_DESCRIPTION_LENGTH = 128; MAX_ADAPTER_ADDRESS_LENGTH = 8; type //------IP address structures--------------------------------------------------- PIP_ADDRESS_STRING = ^IP_ADDRESS_STRING; IP_ADDRESS_STRING = array[0..15] of char; // IP as string PIP_ADDR_STRING = ^IP_ADDR_STRING; IP_ADDR_STRING = record Next: PIP_ADDR_STRING; IpAddress: IP_ADDRESS_STRING; IpMask: IP_ADDRESS_STRING; Context: DWORD; end; //------ADAPTER INFO STRUCTURES------------------------------------------------- PIP_ADAPTER_INFO = ^IP_ADAPTER_INFO; IP_ADAPTER_INFO = record Next: PIP_ADAPTER_INFO; ComboIndex: DWORD; AdapterName: array[1..MAX_ADAPTER_NAME_LENGTH 4] of char; Description: array[1..MAX_ADAPTER_DESCRIPTION_LENGTH 4] of char; AddressLength: UINT; Address: array[1..MAX_ADAPTER_ADDRESS_LENGTH] of byte; Index: DWORD; aType: UINT; DHCPEnabled: UINT; CurrentIPAddress: PIP_ADDR_STRING; IPAddressList: IP_ADDR_STRING; GatewayList: IP_ADDR_STRING; DHCPServer: IP_ADDR_STRING; HaveWINS: BOOL; PrimaryWINSServer: IP_ADDR_STRING; SecondaryWINSServer: IP_ADDR_STRING; LeaseObtained: LongInt; LeaseExpires: LongInt; SpareStuff: array [1..200] of char; end; function GetAdaptersInfo(pAdapterInfo: PIP_ADAPTER_INFO; pOutBufLen: PULONG): DWORD; stdcall; external 'Iphlpapi.dll' name 'GetAdaptersInfo'; ... procedure TForm1.Button2Click(Sender: TObject); const AddrLen = 6; var AdapterInfo: IP_ADAPTER_INFO; ret: DWORD; i: integer; Next: PIP_ADAPTER_INFO; sMAC: string; OutBufLen: ULONG; begin OutBufLen := SizeOf(IP_ADAPTER_INFO); ret:= GetAdaptersInfo(@AdapterInfo, @OutBufLen); if ret = 0 then begin Next:= @AdapterInfo; repeat Memo1.Lines.Add('Description: ' Next^.Description); sMAC := 'MAC address: '; for i := 0 to AddrLen do begin sMAC := sMAC IntToHex(Next^.Address[i], 2); if i <> AddrLen then sMAC := sMAC '-'; end; Memo1.Lines.Add(sMAC); Next:= AdapterInfo.Next; until Next = nil; end; end; |
cjtsif
一般會員 發表:12 回覆:13 積分:5 註冊:2002-09-18 發送簡訊給我 |
|
conundrum
尊榮會員 發表:893 回覆:1272 積分:643 註冊:2004-01-06 發送簡訊給我 |
|
timhuang
尊榮會員 發表:78 回覆:1815 積分:1608 註冊:2002-07-15 發送簡訊給我 |
|
cjtsif
一般會員 發表:12 回覆:13 積分:5 註冊:2002-09-18 發送簡訊給我 |
|
timhuang
尊榮會員 發表:78 回覆:1815 積分:1608 註冊:2002-07-15 發送簡訊給我 |
111 就是 ERROR_BUFFER_OVERFLOW, 也就是分配給 GetAdaptersInfo 的傳入記憶體不足以寫入所有網卡的資訊, 所以應該是你的電腦有多張網卡的關係. 接下來就修正一下程式以改進這個問題, 另外弟第一篇中的 IP_ADAPTER_INFO record(struct) 有誤, 對照微軟的網站說明, 最後的 SpareStuff: array [1..200] of char; 是多餘的, 請拿掉, 也就是改為:
IP_ADAPTER_INFO = record Next: PIP_ADAPTER_INFO; ComboIndex: DWORD; AdapterName: array[1..MAX_ADAPTER_NAME_LENGTH 4] of char; Description: array[1..MAX_ADAPTER_DESCRIPTION_LENGTH 4] of char; AddressLength: UINT; Address: array[1..MAX_ADAPTER_ADDRESS_LENGTH] of byte; Index: DWORD; aType: UINT; DHCPEnabled: UINT; CurrentIPAddress: PIP_ADDR_STRING; IPAddressList: IP_ADDR_STRING; GatewayList: IP_ADDR_STRING; DHCPServer: IP_ADDR_STRING; HaveWINS: BOOL; PrimaryWINSServer: IP_ADDR_STRING; SecondaryWINSServer: IP_ADDR_STRING; LeaseObtained: LongInt; LeaseExpires: LongInt;再來一個就是解決放不下的問題, 其實可以直接先 call 一次傳入 nil 的方式來取得所需要的空間, 如: GetAdaptersInfo(nil, @OutBufLen); 這個回傳值一定是 111 的, 也就是給的 struct 空間不足的回傳結果, 但重點在於 OutBufLen 會傳回所需要的大小, 接下來分配足夠的空間給他用就行了, 如下: procedure TForm1.Button2Click(Sender: TObject); const AddrLen = 6; var PAdapterInfo: PIP_ADAPTER_INFO; ret: DWORD; i: integer; Next: PIP_ADAPTER_INFO; sMAC: string; OutBufLen: ULONG; begin GetAdaptersInfo(nil, @OutBufLen); // to get the required size // alloc memory size = OutBufLen PAdapterInfo := AllocMem(OutBufLen); ret:= GetAdaptersInfo(PAdapterInfo, @OutBufLen); if ret = 0 then begin Next:= PAdapterInfo; repeat Memo1.Lines.Add('Description: ' Next^.Description); sMAC := 'MAC address: '; for i := 0 to AddrLen do begin sMAC := sMAC IntToHex(Next^.Address[i], 2); if i <> AddrLen then sMAC := sMAC '-'; end; Memo1.Lines.Add(sMAC); Next:= Next^.Next; until Next = nil; end; FreeMem(PAdapterInfo, OutBufLen); end;之所以你會得到 111 的回傳值是因為前一個範例直接傳入一個 struct 而已, 若僅一張網卡的話, 不會出錯, 但多張網卡時會回傳 111, 再分配足夠的記憶體給該 api 即可!! 上面的範例直接改為先問要多少記憶體再來給 該 api 使用, 減少一些不必要的程式碼, 比較有效率啦.. 有蠻多 api 的用法會類似這種型態, 之前弟沒注意到 sorry!! |
pcboy
版主 發表:177 回覆:1838 積分:1463 註冊:2004-01-13 發送簡訊給我 |
執行完 Memo1.Lines.Add('Description: ' Next^.Description); 產生下面錯誤 Project C:\Documents and Settings\ms\桌面\test\Project1.exe faulted with message: 'access violation at 0x7c9577c9: write of address 0x00040fdc'. Process Stopped. Use Step or Run to continue. 請問該如何解決 ? 謝謝 ~
------
能力不足,求助於人;有能力時,幫幫別人;如果您滿意答覆,請適時結案! 子曰:問有三種,不懂則問,雖懂有疑則問,雖懂而想知更多則問! |
timhuang
尊榮會員 發表:78 回覆:1815 積分:1608 註冊:2002-07-15 發送簡訊給我 |
|
squall36
一般會員 發表:4 回覆:2 積分:1 註冊:2006-07-31 發送簡訊給我 |
|
chenbear
一般會員 發表:8 回覆:6 積分:2 註冊:2002-08-01 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |