设为首页 收藏本站
查看: 1254|回复: 0

[经验分享] Delphi 如何判断当前网卡是物理网卡(有线网卡,无线网卡)还是虚拟网卡

[复制链接]

尚未签到

发表于 2017-6-23 08:38:14 | 显示全部楼层 |阅读模式
  MAC地址作为硬件唯一标识,在很多时候会被使用,如在软件授权方面,很多软件在产生机器码时会采用CPUID或MAC地址,或使用MAC地址来做一对一绑定。
  相信很多人会碰到以下问题:
  1)获取的是VMWare的网卡MAC地址
  2)获取的是VPN的网卡MAC地址
  VMWare或VPN软件的安装卸载都会导致获取的MAC地址变化,所以我们需要正确获取当前物理网卡的MAC地址。
  下面是根据网卡实例ID判断是否为物理网卡的Delphi代码(RAD Studio 10.1版本的):



const
NCF_VIRTUAL  =$01; //  说明组件是个虚拟适配器
NCF_SOFTWARE_ENUMERATED = $02;//  说明组件是一个软件模拟的适配器
NCF_PHYSICAL = $04; //  说明组件是一个物理适配器
NCF_HIDDEN = $08;  //说明组件不显示用户接口
NCF_NO_SERVICE = $10; //  说明组件没有相关的服务(设备驱动程序)
NCF_NOT_USER_REMOVABLE = $20;  // 说明不能被用户删除(例如,通过控制面板或设备管理器)
NCF_MULTIPORT_INSTANCED_ADAPTER  = $40; //  说明组件有多个端口,每个端 口作为单独的设备安装。
//  每个 端口有自己的hw_id(组件ID) 并可被单独安装,
//  这只适合于 EISA适配器
NCF_HAS_UI = $80; // 说明组件支持用户接口(例如,Advanced Page或Customer  Properties Sheet)
NCF_FILTER = $400; //  说明组件是一个过滤器
function IsPhysicalAdapter(sAdapterGUID: string; bOnlyPCI: Boolean=False):Boolean;
const
NET_CARD_KEY_PATH =
'SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}';
var
Reg: TRegistry;
sList: TStrings;
vCharacteristics: DWORD;
I: Integer;
begin
Result := False;
sList:=TStringList.Create;
Reg:=TRegistry.Create;
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if not Reg.OpenKey(NET_CARD_KEY_PATH, False) then
Exit;
Reg.GetKeyNames(sList);
Reg.CloseKey;
if sList.Count>0 then
for I := 0 to Pred(sList.Count) do
if Reg.OpenKey(NET_CARD_KEY_PATH+'\'+sList.Strings[I], False) then
begin
try
if sAdapterGUID.ToUpper.Trim.Equals(Reg.ReadString('NetCfgInstanceId').ToUpper.Trim) then
begin
vCharacteristics := DWORD(Reg.ReadInteger('Characteristics'));
Result := (NCF_PHYSICAL and vCharacteristics) = NCF_PHYSICAL;
Break;
end;
finally
Reg.CloseKey;
end;
end;
finally
Reg.Free;
sList.Free;
end;
end;
  上面IsPhysicalAdapter的参数网卡实例ID通过GetAdaptersInfo即可得到,综合起来的具体代码如下:
  注意:
  调用 GetAdaptersInfo 可以直接引用下面2个单元
  Winapi.IpTypes,
  Winapi.IpHlpApi



function GetMacAddress(): string;
var
dwRet: DWORD;
AI,Work : PIpAdapterInfo;
sGUID, sTmp, sLastMAC, sFirstMAC: string;
I: Integer;
uSize: ULONG;
begin
Result := '';
sLastMAC := '';
sFirstMAC := '';
uSize := SizeOf(TIpAdapterInfo);
GetMem(AI,uSize);
dwRet := GetAdaptersInfo(AI,uSize);
if (dwRet = ERROR_BUFFER_OVERFLOW)then
begin
FreeMem(AI);
GetMem(AI,uSize);
dwRet := GetAdaptersInfo(AI,uSize);
end;
try
if (dwRet <> ERROR_SUCCESS)then
Exit;
Work := AI;
while Work<>nil do
begin
try
sGUID := string(AnsiString(Work.AdapterName));
sTmp := string(AnsiString(Work.Description));
// 名称描述出现VMWare,直接忽略
if Pos('VMWare', sTmp)>0 then
Continue;
// 配置的ID地址不正常,忽略
if Work.AddressLength=0 then
Continue;
// 将网卡MAC地址转成字符串
sLastMAC := '';
for I:=0 to Work.AddressLength-1 do
begin
sLastMAC := sLastMAC + Format('%.2x', [Work.Address[I]]);
end;
if sFirstMAC='' then
sFirstMAC := sLastMAC;
// 不是物理网卡,忽略
if not IsPhysicalAdapter(sGUID) then
Continue;
Result := sLastMAC;
//找到第一个物理网卡后退出
        Break;
finally
Work := Work.Next;
end;
end;
// 找不到物理网卡MAC,返回第一个即可
if Result='' then
Result := sFirstMAC;
finally
FreeMem(AI);
end;
end;
  理论上从软件层面是无法直接判断一个网络适配器硬件到底是有线还是无线的,因为不管是miniPCIE还是普通PCI接口的网卡,都可以是有线也可以是无线,
  但是也有以下的方法判断:
  1)网卡可以通过名称描述上判断:一般有线网卡名称上带PCI,无线带WLAN 或Wireless,此方法不依赖于网络是否连接,但对那些自定义驱动名称的高人当然无效
  2)获取网络配置信息,也就是获取网络连接里的整个列表,包含物理网卡和宽带连接,VPN等各种连接设备信息,再查看连接类型,根据MSDN的说明,类型包含ETHERNET/PPP/IEEE80211等等,甚至包含移动手机卡的类型。
3)获取网络速率,和2)一样也是获取网络连接的配置信息,100/10Mbps一般是有线,54Mbps或其他一般为WLAN连接,虽说WLAN并不包含一个最高的速度标准,但是普通2.4G或5G的WIFI速度也快不到哪去。
  注:
  方法 2)和3)中的网络类型和网络速率均是通过 API GetIfEntry配合GetAdaptersInfo 获取(或直接通过 GetIfTable获取)网络配置信息得到的,代码MSDN也有
  具体查看MSDN中对此函数返回的结构体MIB_IFROW字段dwType和dwSpeed的说明,除了类型速率,也包含其他非常多的信息。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-387075-1-1.html 上篇帖子: 打开虚拟机时显示不是有效的虚拟机配置文件是什么原因啊 下篇帖子: Kali Linux 2016.2初体验使用总结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表