有需求才有創造,有了問題纔會想着去解決,那麼我這裏的獲取MAC地址的第4種方法也是在這種情況下產生的。因爲公司有一個服務器產品,要寫一個註冊模塊,而註冊模塊需要獲取硬件信息,而硬件信息有很多,可以是硬盤序列號,CPU序列號,和網卡MAC,我首先使用的是硬盤序列號,因爲GOOGLE一下一大堆,我要感謝所有這些無私奉獻自己智慧結晶的可愛的人。
很快地寫完一個註冊模塊,經過幾個PC機,筆記本的測試,一切OK,以爲可以run anywhere了,就提交給項目組了,以爲萬事大吉,過了很長時間,產品出爐了,拿出去用了,可以用戶那邊根本取不到機器信息。剛開始還納悶,但是後來得知用戶那邊用的是服務器是SCIS硬盤。後來還是找不到既能獲取普通硬盤的序列號也能獲取SCIS硬盤的序列號通用的資料。
因爲這個原因我後來就轉向網卡的MAC,應該說網卡的MAC獲取也很方便的,因爲有那些可愛的人的無私奉獻,我通過GOOGLE找到了《取得系統中網卡MAC地址的三種方法》,URL爲: http://dev.csdn.net/develop/article/7/7609.shtm. 文章寫的很好,寫的非常有條理,在這裏我還要向作者Borland 和譯者cker表示最誠摯的謝意。
看了這個文章,我又很快地寫好了一個註冊模塊,我用的是第1種方法,是由網卡的MAC爲基本信息的,這次我先還是在幾個PC機上做測試,不過這次比較幸運,問題馬上就出現了,在一個裝有防火牆軟件的機器上無法獲取MAC,原因cker已經說明了,是防火牆將文件共享服務關閉了,這樣就獲取不了MAC地址。
而使用第二種,根本就不是那回事,我在自己的開發機上就出事了,當然也不能用了。
第三種方法用的事SNMP,但不是每個機器都是安裝了這個協議的,因此也不是一種通用的好方法。
在三種方法都沒有辦法行得通的情況下,一天我在看一本LINUX書的時候看到了管道,可以將輸出重定向到管道,哈哈,這個時候也就想到了,用命令行config /all來獲取網卡相關的信息,然後我重定向到管道,就可以獲取各種和網卡相關的信息了,哈哈,於是這第四種方法也就出爐了。
這種方法的有點是你只要能夠在機器上執行“ipconfig /all”命令你就可以得到MAC地址,而這個命令在所有的網卡可用的情況下都是可用的。
另外你要遍歷所有的網卡MAC,那麼只需提取出所有的MAC段即可。
程序的過程也清晰簡單:
1. 創建一個無名管道。
2. 創建一個IPCONFIG 的進程,並將輸出重定向到管道。
3. 從管道獲取命令行返回的所有信息放入緩衝區lpszBuffer。
4. 從緩衝區lpszBuffer中獲得抽取出MAC地址串。
通過我這個列子你也可以用來獲取可以通過命令行方式來取得的信息,比如說主機名,IP地址等等。
源代碼:
文件 GetMac.cpp:
//////////////////////////////////////////////////////////////////////////
// 描述: 通過命令行方式得到MAC地址
// 作者: 郭洪鋒
// 日期: 2005年7月1日
// email: [email protected]
/////////////////////////////////////////////////////////////////////////
#include <string>
#include <iostream>
using namespace std;
//命令行輸出緩衝大小
const long MAX_COMMAND_SIZE = 10000;
//獲取MAC命令行
char szFetCmd[] = "ipconfig /all";
//網卡MAC地址的前導信息
const string str4Search = "Physical Address. . . . . . . . . : ";
//用命令行方式獲取網卡MAC地址
BOOL GetMacByCmd(char *lpszMac);
////////////////////////////////////////////////////////////////////////////
// 函數名: GetMacByCmd(char *lpszMac)
// 參數:
// 輸入: void
// 輸出: lpszMac,返回的MAC地址串
// 返回值:
// TRUE: 獲得MAC地址。
// FALSE: 獲取MAC地址失敗。
// 過程:
// 1. 創建一個無名管道。
// 2. 創建一個IPCONFIG 的進程,並將輸出重定向到管道。
// 3. 從管道獲取命令行返回的所有信息放入緩衝區lpszBuffer。
// 4. 從緩衝區lpszBuffer中獲得抽取出MAC串。
//
// 提示:可以方便的由此程序獲得IP地址等其他信息。
// 對於其他的可以通過其他命令方式得到的信息只需改變strFetCmd 和
// str4Search的內容即可。
///////////////////////////////////////////////////////////////////////////
BOOL GetMacByCmd(char *lpszMac)
{
//初始化返回MAC地址緩衝區
memset(lpszMac, 0x00, sizeof(lpszMac));
BOOL bret;
SECURITY_ATTRIBUTES sa;
HANDLE hReadPipe,hWritePipe;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
//創建管道
bret = CreatePipe(&hReadPipe, &hWritePipe, &sa, 0);
if(!bret)
{
return FALSE;
}
//控制命令行窗口信息
STARTUPINFO si;
//返回進程信息
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);
si.hStdError = hWritePipe;
si.hStdOutput = hWritePipe;
si.wShowWindow = SW_HIDE; //隱藏命令行窗口
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
//創建獲取命令行進程
bret = CreateProcess (NULL, szFetCmd, NULL, NULL, TRUE, 0, NULL,
NULL, &si, &pi );
char szBuffer[MAX_COMMAND_SIZE+1]; //放置命令行輸出緩衝區
string strBuffer;
if (bret)
{
WaitForSingleObject (pi.hProcess, INFINITE);
unsigned long count;
CloseHandle(hWritePipe);
memset(szBuffer, 0x00, sizeof(szBuffer));
bret = ReadFile(hReadPipe, szBuffer, MAX_COMMAND_SIZE, &count, 0);
if(!bret)
{
//關閉所有的句柄
CloseHandle(hWritePipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(hReadPipe);
return FALSE;
}
else
{
strBuffer = szBuffer;
long ipos;
ipos = strBuffer.find(str4Search);
//提取MAC地址串
strBuffer = strBuffer.substr(ipos+str4Search.length());
ipos = strBuffer.find("/n");
strBuffer = strBuffer.substr(0, ipos);
}
}
memset(szBuffer, 0x00, sizeof(szBuffer));
strcpy(szBuffer, strBuffer.c_str());
//去掉中間的“00-50-EB-0F-27-82”中間的'-'得到0050EB0F2782
int j = 0;
for(int i=0; i<strlen(szBuffer); i++)
{
if(szBuffer[i] != '-')
{
lpszMac[j] = szBuffer[i];
j++;
}
}
//關閉所有的句柄
CloseHandle(hWritePipe);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(hReadPipe);
return TRUE;
}
文件GetMacByCmd.cpp:
#include "stdafx.h"
#include <iostream.h>
#include <string>
#include "windows.h"
using namespace std;
extern BOOL GetMacByCmd(char *lpszMac);
void main (int argc, char *argv[])
{
char lpszMac[128];
memset(lpszMac, 0x00, sizeof(lpszMac));
//獲取MAC
GetMacByCmd(lpszMac);
//打印出MAC
cout << lpszMac << endl;
//寫入文件
FILE *fp = NULL;
fp = fopen("c://1.txt", "w");
fwrite(lpszMac, sizeof(char), strlen(lpszMac), fp);
fclose(fp);
}