该方法有BUG,如果网卡信息中包含有字符“#”(常见于一些安装了虚拟机的机器中),管道读取CMD输出内容时可能会假死,不会返回。建议使用GetAdaptersAddresses函数来获取MAC地址。具体请参照《使用GetAdaptersAddresses函数获取物理MAC地址》
1、头文件
// Temporary.h
//
#ifndef _TEMPORARY_H_
#define _TEMPORARY_H_
#include <vector>
class CTemporary
{
public:
CTemporary() {};
BOOL GetMacAddr(OUT std::vector<CString>& vtMacAddr);
private:
BOOL _AnalyseCmdResult(LPCSTR pszCmdRes,
std::vector<CString>& vtMacAddr);
};
#endif // !_TEMPORARY_H_
2、源文件
// Temporary.cpp
//
#include "Temporary.h"
CTemporary::CTemporary()
{
}
BOOL CTemporary::GetMacAddr(std::vector<CString>& vtMacAddr)
{
CString sCmd(_T("IPCONFIG /ALL"));
BOOL bResult = FALSE;
SECURITY_ATTRIBUTES securityAttr;
HANDLE hReadPipe = NULL, hWritePipe = NULL;
securityAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
securityAttr.lpSecurityDescriptor = NULL;
securityAttr.bInheritHandle = TRUE;
// 创建管道
bResult = CreatePipe(&hReadPipe, &hWritePipe, &securityAttr, 0);
if (FALSE == bResult)
{
return FALSE;
}
PROCESS_INFORMATION processInfo;
ZeroMemory(&processInfo, sizeof(processInfo));
do
{
// 控制命令行窗口信息
STARTUPINFO startupInfo;
startupInfo.cb = sizeof(STARTUPINFO);
GetStartupInfo(&startupInfo);
startupInfo.hStdError = hWritePipe;
startupInfo.hStdOutput = hWritePipe;
startupInfo.wShowWindow = SW_HIDE; // 隐藏命令行窗口
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
// 创建获取命令行进程
bResult = CreateProcess(NULL, sCmd.GetBuffer(), NULL, NULL,
TRUE, 0, NULL, NULL, &startupInfo, &processInfo);
sCmd.ReleaseBuffer();
if (FALSE == bResult)
{
break;
}
WaitForSingleObject(processInfo.hProcess, INFINITE);
const UINT uiBuffSize = 1024 * 10;
PSTR pszBuffer = new char[uiBuffSize]; // 放置命令行输出缓冲区
ZeroMemory(pszBuffer, uiBuffSize);
DWORD dwCount = 0;
bResult = ReadFile(hReadPipe, pszBuffer, uiBuffSize, &dwCount, 0);
if (FALSE == bResult)
{
break;
}
bResult = _AnalyseCmdResult(pszBuffer, vtMacAddr);
} while (FALSE);
// 关闭所有的句柄
if (hWritePipe)
{
CloseHandle(hWritePipe);
}
if (processInfo.hProcess)
{
CloseHandle(processInfo.hProcess);
}
if (processInfo.hThread)
{
CloseHandle(processInfo.hThread);
}
if (hReadPipe)
{
CloseHandle(hReadPipe);
}
return bResult;
}
BOOL CTemporary::_AnalyseCmdResult(LPCSTR pszCmdRes,
std::vector<CString>& vtMacAddr)
{
const char szSearchTarget[2][128] = {
"物理地址. . . . . . . . . . . . . : ",
"Physical Address. . . . . . . . . : "
};
char szMacAddr[24];
LPCSTR pEndIndex = NULL;
LPCSTR pStartIndex = NULL;
const char szIgnoreMac[] = "00-00-00";
for (UINT i = 0; i < 2; i++)
{
pStartIndex = pszCmdRes;
do
{
pStartIndex = strstr(pStartIndex, szSearchTarget[i]);
if (NULL == pStartIndex)
{
break;
}
pStartIndex += strlen(szSearchTarget[i]);
pEndIndex = strchr(pStartIndex, '\r');
if (NULL == pEndIndex)
{
pEndIndex = strchr(pStartIndex, '\n');
if (NULL == pEndIndex)
{
ATLASSERT(NULL != pEndIndex);
continue;
}
}
strncpy_s(szMacAddr, 24, pStartIndex, pEndIndex - pStartIndex);
pStartIndex = pEndIndex;
if (szMacAddr == strstr(szMacAddr, szIgnoreMac))
{
continue;
}
vtMacAddr.push_back(CString(ATL::CA2T(szMacAddr)));
} while (TRUE);
}
return vtMacAddr.size() ? TRUE : FALSE;
}
3、测试与样例
#include "Temporary.h"
#include <iostream>
void main()
{
std::vector<CString> vtMacAddr;
CTemporary temporary;
if (FALSE == temporary.GetMacAddr(vtMacAddr))
{
std::cout << _T("Get mac address failed.") << std::endl;
return;
}
for (UINT uiIndex = 0; uiIndex < vtMacAddr.size(); uiIndex++)
{
std::cout << vtMacAddr[uiIndex] << std::endl;
}
system("pause");
}