2019年9月

首页2019年9月
26
Sep
0

判断当前网卡是物理网卡(有线网卡,无线网卡)还是虚拟网卡

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的说明,除了类型速率,也包含其他非常多的信息。

26
Sep
0

Delphi常用类型及定义单元

Type Unit
Date SysUtils
DeleteFile SysUtils or Windows (different versions)
DispatchInvokeError ComObj
DWORD Windows
EDatabaseError DB
EncodeDateTime DateUtils
_Stream ADODB_TLB
akTop, akLeft, akRight, akBottom Controls
Application (the variable not a type) Forms
Beep SysUtils or Windows (different functions)
CGID_EXPLORER ShlObj
CN_BASE Controls
CoInitialize ActiveX
CopyFile Windows
CoUnInitialize ActiveX
CreateComObject ComObj
CreateOleObject ComObj
EnumWindows Windows
EOleError ComObj
EOleException ComObj
EOleSysError ComObj
Exception SysUtils
ExtractFileName SysUtils
FileExists SysUtils
FileOpen SysUtils
FILETIME Windows
FindFirst SysUtils
FindFirstFile Windows
FindWindow Windows
FlushFileBuffers Windows
fmOpenRead SysUtils
fmShareDenyWrite SysUtils
Format SysUtils
FormatDateTime SysUtils
FreeAndNil SysUtils
fsBold Graphics
ftWideString DB
ftString DB
GetCurrentProcessId Windows
GetEnvironmentVariable SysUtils or Windows (different versions)
GetFileAttributes Windows
GetFileVersionInfoSize Windows
GetWindowLong Windows
GetStdHandle Windows
HDC Windows
HFont Windows
HINTERNET WinInet
HKEY_CURRENT_USER Windows
IHTMLDocument2 MSHTML or MSHTML_TLB
IHTMLElement MSHTML or MSHTML_TLB
IHTMLEventObj MSHTML or MSHTML_TLB
IID_IWebBrowser2 SHDocVw or SHDocVw_TLB
IMessage CDO_TLB
InternetClosehandle WinInet
InternetOpenUrl WinInet
InternetReadFile WinInet
IntToHex SysUtils
IntToStr SysUtils
IOleCommandTarget ActiveX
IOleContainer ActiveX
IPersistStreamInit ActiveX
IsSameDay DateUtils
IStream ActiveX
IWebBrowser2 SHDocVw or SHDocVw_TLB
LockWindowUpdate Windows
Log10 Math
LowerCase SysUtils
LPSTR Windows
MAX_PATH Windows
MessageBox Windows
MessageDlg Dialogs
MB_YESNO, MB_OK etc Windows
MinutesBetween DateUtils
Now SysUtils
OleInitialize ActiveX
OleUninitialize ActiveX
PItemIDList ShlObj
POleCmd ActiveX
POleCmdText ActiveX
PostMessage Windows
PosX StrUtils
QueryHighPerformanceCounter Windows
QueryPerformanceCounter Windows
ReverseString StrUtils
RoundTo Math
SendMessage Windows
SetForegroundWindow Windows
ShellExecute ShellAPI
ShellExecuteEx ShellAPI
SHGetFileInfo ShellAPI
SHFILEINFO ShellAPI
ShowMessage Dialogs
Sleep SysUtils
StrAlloc SysUtils
StrPas SysUtils
StrToDate SysUtils
StrToInt SysUtils
StrToIntDef SysUtils
TAdoConnection ADODB
TAdoQuery ADODB
TAlign Controls
TAlignment Classes
TAnchors Controls
TBitmap Graphics
TBlobStream DBTables
TCanvas Graphics
TClientSocket ScktComp
TComboBox StdCtrls
TComponent Classes
TControl Controls or QControls
TCriticalSection SyncObjs
TField DB
TFieldType DB
TFileName SysUtils
TFileStream Classes
TForm Forms
TFrame Forms
TGroupBox StdCtrls
TIID ActiveX
TIniFile IniFiles
TJPEGImage Jpeg
TLabel StdCtrls
TList Classes
TMemo StdCtrls
TMemoryStream Classes
TMouseButton Controls
TNofityEvent Classes
TObjectList Contnrs
TOSVersionInfo Windows
TPanel ExtCtrls
TPoint Types
TProcessEntry32 TlHelp32
TProgressBar ComCtrls or QComCtrls
TRadioButton StdCtrls
TRadioGroup ExtCtrls
TRect Types
TRegistry Registry
Trim SysUtils
TRoundToRange Math
TSearchRec SysUtils
TSize Windows
TSocketAddrIn Winsock
TStaticText StdCtrls
TStream Classes
TStringList Classes
TStrings Classes
TStringStream Classes
TSystemTime Windows
TTable DBTables
TTabSheet ComCtrls
TThread Classes
TTreeNode ComCtrls
TWebBrowser SHDocVw or SHDocVw_TLB
TWinSocketStream ScktComp
TWMCommand Messages
Unassigned Variants
VarArrayCreate Variants
VarArrayOf Variants
VirtualProtect Windows
WM_USER Messages
YearOf DateUtils
DaysInAMonth DateUtils