使用CMD命令和管道獲取MAC地址

該方法有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");
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章