GetAdaptersInfo 可以获得本机所有网卡的信息,然而这些网卡中可能包括虚拟网卡。例如,若安装了 VMWare 或者某些 VPN 客户端软件,则会出现若干虚拟网卡。它们在形式上与物理网卡几乎没有区别。 ipconfig 将它们与本地物理网卡等同对待。

有些人建议使用 MAC 地址中的 "locally administread bit" 来区分。而事实证明这是靠不住的。 http://hi.baidu.com/xzq2000/blog ... cd762f07088b95.html
是目前我找到的比较实用的办法。

其原理是先由 GetAdaptersInfo 获取所有网卡的基本信息。然后利用网卡名去注册表中查找对应的硬件信息。若是物理网卡,其硬件信息中通常会包含 PCI 。

例如,某个网卡的名为 {ACA306D0-1D69-4116-BC2B-919B428AD084}。
他在注册表中的信息所在位置为: 
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E972-E325-11CE-BFC1-08002BE10318}/{ACA306D0-1D69-4116-BC2B-919B428AD084}/Connection

若PnpInstanceID的值以PCI开头,说明是物理网卡,MediaSubType为01则是常见网卡,02为无线网卡。

以下代码是从上述网页中转贴。该例中仅当网卡为有线物理网卡时才返回true.

[Copy to clipboard]  [ - ]

CODE:

bool IsLocalAdapter ( const char *pAdapterName ) const
...{
    BOOL ret_value = FALSE;

#define NET_CARD_KEY "System/CurrentControlSet/Control/Network/{4D36E972-E325-11CE-BFC1-08002BE10318}"
    char szDataBuf[MAX_PATH+1];
    DWORD dwDataLen = MAX_PATH;
    DWORD dwType = REG_SZ;
    HKEY hNetKey = NULL;
    HKEY hLocalNet = NULL;

if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, NET_CARD_KEY, 0, KEY_READ, &hNetKey))
        return FALSE;
    sprintf(szDataBuf, "%s/Connection", pAdapterName);
    if(ERROR_SUCCESS != RegOpenKeyEx(hNetKey ,szDataBuf ,0 ,KEY_READ, &hLocalNet))
    ...{
        RegCloseKey(hNetKey);
        return FALSE;
    }
    if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, "MediaSubType", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
    ...{
        goto ret;
    }
    if (*((DWORD *)szDataBuf)!=0x01)
        goto ret;
    dwDataLen = MAX_PATH;
    if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, ";PnpInstanceID", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
    ...{
        goto ret;
    }
    if (strncmp(szDataBuf, ";PCI", strlen(";PCI")))
        goto ret;

ret_value = TRUE;

ret:
    RegCloseKey(hLocalNet);
    RegCloseKey(hNetKey);

return ret_value!=0;

}

获得正确本地MAC地址,区分虚拟网卡

[Copy to clipboard]  [ - ]

CODE:

void GetLocalMAC(char *buf)
{
IP_ADAPTER_INFO *IpAdaptersInfo =NULL;
IP_ADAPTER_INFO *IpAdaptersInfoHead =NULL;

IpAdaptersInfo = (IP_ADAPTER_INFO *) GlobalAlloc(GPTR, sizeof(IP_ADAPTER_INFO ));

if (IpAdaptersInfo == NULL)
{
  return;
}

DWORD dwDataSize = sizeof( IP_ADAPTER_INFO );
DWORD dwRetVal = GetAdaptersInfo(IpAdaptersInfo,&dwDataSize);

if ( ERROR_SUCCESS != dwRetVal)
{
  GlobalFree( IpAdaptersInfo );
  IpAdaptersInfo = NULL;

if( ERROR_BUFFER_OVERFLOW == dwRetVal)
  {
   IpAdaptersInfo =(IP_ADAPTER_INFO *) GlobalAlloc( GPTR, dwDataSize );
   if (IpAdaptersInfo == NULL)
   {
    return;
   }
   if ( ERROR_SUCCESS != GetAdaptersInfo( IpAdaptersInfo, &dwDataSize ))
   {
    GlobalFree( IpAdaptersInfo );
    return;
   }

}
  else
  {
   return;
  }

}

//Save the head pointer of IP_ADAPTER_INFO structures list.
IpAdaptersInfoHead = IpAdaptersInfo;

do{
  if (IsLocalAdapter(IpAdaptersInfo->AdapterName))
  {
   sprintf(buf,"%02x-%02x-%02x-%02x-%02x-%02x",
    IpAdaptersInfo->Address[0],
    IpAdaptersInfo->Address[1],
    IpAdaptersInfo->Address[2],
    IpAdaptersInfo->Address[3],
    IpAdaptersInfo->Address[4],
    IpAdaptersInfo->Address[5]);
   //
   break;
  }

IpAdaptersInfo = IpAdaptersInfo->Next;

}while (IpAdaptersInfo);

if (IpAdaptersInfoHead != NULL)
{
  GlobalFree( IpAdaptersInfoHead );
}
}

BOOL IsLocalAdapter(char *pAdapterName)
{
BOOL ret_value = FALSE;

#define NET_CARD_KEY _T("System//CurrentControlSet//Control//Network//{4D36E972-E325-11CE-BFC1-08002BE10318}")
char szDataBuf[MAX_PATH+1];
DWORD dwDataLen = MAX_PATH;
DWORD dwType = REG_SZ;
HKEY hNetKey = NULL;
HKEY hLocalNet = NULL;

if(ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, NET_CARD_KEY, 0, KEY_READ, &hNetKey))
  return FALSE;
wsprintf(szDataBuf, "%s//Connection", pAdapterName);
if(ERROR_SUCCESS != RegOpenKeyEx(hNetKey ,szDataBuf ,0 ,KEY_READ, &hLocalNet))
{
  RegCloseKey(hNetKey);
  return FALSE;
}
if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, "MediaSubType", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
{
  goto ret;
}
if (*((DWORD *)szDataBuf)!=0x01)
  goto ret;
dwDataLen = MAX_PATH;
if (ERROR_SUCCESS != RegQueryValueEx(hLocalNet, ";PnpInstanceID", 0, &dwType, (BYTE *)szDataBuf, &dwDataLen))
{
  goto ret;
}
if (strncmp(szDataBuf, ";PCI", strlen(";PCI")))
  goto ret;

ret_value = TRUE;

ret:
RegCloseKey(hLocalNet);
RegCloseKey(hNetKey);

return ret_value;
}

以前的那个无法区分虚拟网卡,所以在得到MAC地址时会出现大量重复的现象,非常麻烦,这个就没有问题了。

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Network/{4D36E972-E325-11CE-BFC1-08002BE10318}/{ACA306D0-1D69-4116-BC2B-919B428AD084}/Connection
网卡在注册表里的位置

区分PnpInstanceID,如果前面有PCI就是本机的真实网卡,MediaSubType为01则是常见网卡,02为无线网卡。

判断是本地网卡是物理网卡还是虚拟网卡相关推荐

  1. linux上使用tun/tap设备模拟一个虚拟网卡,并将该虚拟网卡连接到新创建的网桥上

    目录 linux上使用tun/tap设备模拟一个虚拟网卡,并将该虚拟网卡连接到新创建的网桥上 一.tun/tap设备简介 二.在linux上使用tun/tap设备模拟一个虚拟网卡 三. 创建网桥连接到 ...

  2. linux 虚拟网卡与物理网卡关系,Linux Macvlan的虚拟网卡与宿主物理网卡之间的Bridge通信问题...

    周末的时候写了一篇关于Docker底层支撑技术的文章: 以firejail sandbox解析Docker核心原理依赖的四件套 : https://blog.csdn.net/dog250/artic ...

  3. linux没有网卡装置,基于Linux的虚拟网卡实现方法、装置、设备及介质与流程

    技术特征: 1.一种基于linux的虚拟网卡实现方法,其特征在于:包括以下步骤: s1,vpn系统通过ppp接口获取带有ppp协议的网络封包,从该网络封包中读取ppp协议数据,从该ppp协议数据中提取 ...

  4. wireshark抓虚拟网卡_抓取Vmware虚拟网卡上的网络数据包

    抓取 Vmware 虚拟网卡上的网络数据包 首先简单介绍一下 Vmware 中的几种网络连接方式, Vmware 安装后默认安装 3 个虚拟 网卡: Vmnet0 . Vmnet1 . Vmnet8 ...

  5. 服务器虚拟网卡卸载不掉,怎么彻底卸载虚拟网卡设备。 彻底卸载虚拟网卡设备的方法。...

    今天给大家带来怎么彻底卸载虚拟网卡设备.,彻底卸载虚拟网卡设备的方法.,让您轻松解决问题.网友求助:求助如何卸载虚拟网卡? 具体方法如下:1 使用Win+R调出运行,在其中输入:devmgmt.msc ...

  6. linux 虚拟网卡 源码,Linux的虚拟网卡TUN和TAP

    TUN/TAP 提供了给用户空间程序的包的接收和传输,它可以看成是简单的点对点设备或是 以太网设备.它不是从物理设备接收包,而是从用户空间程序接收包.它发送包不是通过物 理设备来发送包,而是将这些包写 ...

  7. windows下判断网卡是否是虚拟网卡的方式

    windows下判断网卡是否是虚拟网卡的方式 网上流传的判断虚拟网卡的方式通常是判断网卡名称,以PCI开头的网卡都是真实网卡.因为以前网卡都是PCI网卡,不是的就是虚拟网卡.但是这种方式不一定全部正确 ...

  8. nmcli、team虚拟网卡相关练习

    练习前相关配置 查看操作系统版本 [root@rhel8 ~]# cat /etc/redhat-release Red Hat Enterprise Linux release 8.1 Beta ( ...

  9. 虚拟网卡技术-VETH、MACVLAN、IPVLAN

    Linux的网卡驱动中内含了很多"虚拟网卡".早先的文章曾经详细分析过tun,ifb等虚拟网卡,类似的思路,在虚拟化大行其道的趋势下,Linux源码树中不断增加对"网络虚 ...

  10. 使用Oracle VM VirtualBox创建的虚拟机与本地电脑(物理机)搭建局域网

    前言 本人之前在大学做网络攻防实验和一些CI/CD配置的时候,都需要将虚拟机和物理机进行连接,即物理机能通过局域网访问到虚拟机,这个需求虽然偶然会用到,但是每次用的时候都会在网上找好久的资料才能解决这 ...

最新文章

  1. 【硅谷牛仔】DropBox CEO --德鲁休斯敦--找到合适自己的圈子,追逐自己感兴趣的事...
  2. 全球项目多区域数据同步问题解决方案
  3. ligertree内容过多导致崩溃_师傅崩溃了!自身是8年的老师傅,料也没问题,但每次都堵管...
  4. AngularJS学习日记(四)Service和Provider
  5. 三角插值的 Fourier 系数推导
  6. k8s,nginx备份日志脚本
  7. linux php gd库安装,Linux系统gd库安装步骤说明
  8. Anbox 和 LXC 代码规模
  9. java swing 一闪而过_Java代码,为什么图形会一闪而过,怎么修改?
  10. jQuery数据转换与提交
  11. fn:replace()函数
  12. 产品经理是否应该给 UI 设计师的设计稿提意见?
  13. 抖音客新版UI短视频点赞任务系统完美运营级别[等级功能+信誉积分+保证金]
  14. 大型网站的架构设计与演进
  15. python之OrderedDict类
  16. qt5 开发及实例(第4版)_张厚粲现代心理与教育统计学第4版配套章节题库
  17. 微信测试号实现微信网页的分享
  18. 夜神模拟器解决apk无法安装的问题
  19. android 字体倒影,Android实现图片的倒影效果
  20. 数字信号处理——DDS模块设计(3)

热门文章

  1. Qt编写物联网管理平台50-超强跨平台
  2. html 在线预览pdf功能,html中在线预览pdf文件之pdf在线预览插件
  3. 智能镜——7.化妆灯和人体感应篇
  4. Mysql-5.7.21-winx64 绿色版安装
  5. Java String方法
  6. CVE-2022-0543:redis lua沙盒绕过命令执行漏洞复现
  7. 基于Android手机APP健身系统设计
  8. mysql存储过程-游标
  9. 计算机辅助机械设备管理的目标和作用,建筑施工常用机械设备管理及使用模板.doc...
  10. 微软JobHack两天面试经验CSS (Winter Intern Job Hack)